假设我在 C++ 中有以下类,我想检查它们的继承:
车辆
Motorcar
是 Vehicle
Aircraft
是 Vehicle
Biplane
是 Aircraft
是 Vehicle
Helicopter
是 Aircraft
是 Vehicle
。
我想编写一个方法 getClassLineage()
来执行以下操作:
Biplane b;
cout << b.getClassLineage() << endl; // prints "Vehicle--Aircraft--Biplane"
Helicopter h;
cout << h.getClassLineage() << endl; // prints "Vehicle--Aircraft--Helicopter"
Motorcar m;
cout << m.getClassLineage() << endl; // prints "Vehicle--Motorcar"
似乎应该有一种简单的递归方法来做到这一点,只需在父类(super class)中编写一次,而无需在每个派生类中复制一个本质上相同的方法。
假设我们愿意声明(伪代码)Helicopter.className = "Helicopter"
并且
typedef Aircraft baseclass
在每个派生类中,但尽量避免复制和粘贴 getClassLineage()
。
有没有优雅的写法?
(感谢您的想法!)
最佳答案
解决方案1
如果您对修饰名称没问题,那么您可以编写一个免费函数模板:
struct Vehicle {};
struct Aircraft : Vehicle { typedef Vehicle super; };
struct Helicopter : Aircraft { typedef Aircraft super; };
template<typename T>
string getClassLineage()
{
static string lineage = string(typeid(T).name()) +" - " + getClassLineage<typename T::super>();
return lineage;
}
template<>
string getClassLineage<Vehicle>()
{
static string lineage = string(typeid(Vehicle).name());
return lineage;
}
int main() {
cout << getClassLineage<Helicopter>() << endl;
return 0;
}
输出(修饰名):
10Helicopter - 8Aircraft - 7Vehicle
参见ideone:http://www.ideone.com/5PoJ0
如果你愿意,你可以去掉装饰。但这将是特定于编译器的! Here是利用remove_decoration
函数去掉装饰的版本,输出变成:
Helicopter - Aircraft - Vehicle
顺便说一下,正如我所说,remove_decoration
函数的实现是特定于编译器的;此外,这可以用更正确的方式编写,因为我不知道 GCC 考虑的所有情况,而 mangling类名。但我希望您了解基本概念。
解决方案2
如果您可以在每个派生类中重新定义函数,那么这里有一个简单的解决方案:
struct Vehicle
{
string getClassLineage() const { return "Vehicle"; }
};
struct Aircraft : Vehicle
{
string getClassLineage() const { return Vehicle::getClassLineage()+" - Aircraft"; }
};
struct Helicopter : Aircraft
{
string getClassLineage() const { return Aircraft::getClassLineage()+" - Helicopter "; }
};
int main() {
Helicopter heli;
cout << heli.getClassLineage() << endl;
return 0;
}
输出:
Vehicle - Aircraft - Helicopter
查看 ideone 的输出:http://www.ideone.com/Z0Tws
关于c++ - 在 C++ 中反射(reflect)一个类的继承树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5026972/