【发布时间】:2019-06-10 07:18:15
【问题描述】:
我一直在玩模板和继承,但是在对基类执行强制转换时使用带有模板参数的虚函数成员有些奇怪。它们似乎使用“直接继承”工作,但如果我稍后“推迟”继承,它们就不行了。
一点代码来说明:
示例 [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有关吗?
【问题讨论】:
-
CastExA<int>* a3 = (CastExA<int>*) a2;- 你不能使用 C 风格的演员阵容,你需要在这里dynamic_cast。 -
理想情况下是的,但我知道类型将是 CastExA
* 所以应该可以使用它。无论如何,我也尝试动态转换它,但结果相同 -
一般提示:永远不要在 C++ 中进行 C 样式转换。如果您需要这样做,这通常是一个危险信号,表明您做错了。
-
是的,我应该使用 static_cast,我同意
-
密切相关,可能被骗:stackoverflow.com/questions/19528338/…
标签: c++ templates inheritance casting polymorphism