使用模板无法按预期工作进行继承和强制转换
Inheritance and casting with templates not working as expected
我一直在玩模板和继承,但是在对基类执行强制转换时,使用带有模板参数的虚函数成员有些奇怪。它们似乎使用"直接继承"起作用,但如果我稍后"推迟"继承,则不行。
一些代码来说明:
示例 [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有关吗?
即使CastExC
同时继承了CastExA<int>
和CstExB
,CstExB
中h()
的定义也不会覆盖CastExA<int>
中h()
的"定义",因为CastExA<int>
和CstExB
是不相关的。如果您尝试这样做:
CastExBase* a2 = new CastExC();
CastExC* a3 = (CastExC*) a2;
a3->h();
您将收到一个模棱两可的h()
请求。如果要重载,则需要手动执行此操作:
struct CastExC: protected CastExB, public CastExA<int> {
virtual int h() override { return CastExB::h(); }
};
CastExC
中没有h()
。也许这就是原因。
注意:CastExA
和CastExB
不相关。
相关文章:
- 继承模板化转换运算符
- 共享指针继承,而不先显式强制转换
- 事件系统:使用类型转换或联合进行继承
- 从继承的类C++强制转换
- 继承会导致不明确的转换
- 将 void* 强制转换为多个继承类的超类不会调用正确的方法
- C++ 关于类继承的隐式转换
- 使用类继承将单个喜欢的列表转换为双向链表
- 如何将C++继承的带有函数的类转换为C样式?
- C++ MSVC 中的访问冲突,但不在 GCC 中进行多重继承和强制转换
- 模板实例和继承的转换错误
- 为什么 GCC 在使用继承的构造函数时警告我无用的强制转换
- 为什么私有继承对象允许成员函数将派生的*转换为基*,而外部不能
- 在多重继承场景中动态强制转换类型
- 使用模板无法按预期工作进行继承和强制转换
- 将void*强制转换为具有多重继承的类
- 避免在继承的树类中进行下转换
- C++ 中的多重继承转换
- c++错误:继承转换无效
- GCC将私有继承转换为父