我一直在研究模板和继承,但是在执行对基类的转换时使用带有模板参数的虚拟函数成员有些奇怪。它们似乎使用“直接继承”来工作,但是如果以后我“推迟”继承则不能。
一些代码来说明:
示例[1]
struct CastExBase
{
virtual void f() {}
};
template<class RT>
struct CastExA : CastExBase
{
void f() {std::cout << "CastExA" << std::endl;}
virtual void g() {std::cout << "g - A" << std::endl;}
virtual RT h() {std::cout << "h - A" << std::endl;}
};
struct CastExB
{
void execF() {std::cout << "CastExB" << std::endl;}
void g() {std::cout << "g - B" << std::endl;}
int h() {std::cout << "h - B" << std::endl;}
};
struct CastExC :
public CastExA<int>,
protected CastExB
{
void f() override
{
(static_cast<CastExB*>(this))->execF();
}
void g() override
{
(static_cast<CastExB*>(this))->g();
}
};
测试用例:
CastExBase* a2 = new CastExC();
CastExA<int>* a3 = (CastExA<int>*) a2;
a3->g(); // This prints g - B as expected
a3->h(); // This prints h - A ... why???
为什么a3-> h()不显示h-B?
我还尝试了另一种直接从基类继承的测试,在这种情况下它可以正常工作。
示例[2]
struct CastExDBase
{
};
template<class T>
struct CastExD : CastExDBase
{
virtual T f() {std::cout << "CastExD" << std::endl;}
};
struct CastExE : CastExD<int>
{
int f() {std::cout << "CastExE" << std::endl;}
};
测试用例:
CastExDBase* d1 = new CastExE();
CastExD<int>* d2 = (CastExD<int>*) d1;
d2->f(); // This prints CastExE as expected
这与UB有关吗?
答案 0 :(得分:5)
即使CastExC
继承了CastExA<int>
和CstExB
,h()
中CstExB
的定义也不会覆盖{{1}的“定义” h()
中的},因为CastExA<int>
和CastExA<int>
不相关。如果您尝试这样做:
CstExB
您将收到一个对CastExBase* a2 = new CastExC();
CastExC* a3 = (CastExC*) a2;
a3->h();
的模糊请求。如果要过载,则需要手动执行此操作:
h()
答案 1 :(得分:4)
java -jar -Dapp.home="." axian-oxalys.jar
中没有h()
。也许就是这个原因。
注意:CastExC
和CastExA
无关。