多态类作为模板参数时的指针类型转换错误咨询
多态类模板参数转换失败的原因与解决办法
嘿,我来帮你捋清楚这个问题哈!
先看你写的代码和遇到的报错:
class A{ public: virtual ~A() = default; }; class B : public A{}; class C : public A{}; template<typename A> class X{ public: virtual ~X() = default; }; class Y : public X<B>{}; class Z : public X<C>{}; int main(void) { X<A> *test = new Y(); (void)test; return 0; }
错误提示:error: cannot convert 'Y*' to 'X*' in initialization
问题根源
你可能误以为因为B继承自A,所以X<B>和X<A>之间也会有继承或转换关系,但实际上模板类的不同实例化版本是完全独立的类型——哪怕模板参数是父子类,X<B>和X<A>也没有任何继承关联,就像std::vector<B>和std::vector<A>是完全不相关的类一样,自然无法互相转换。
另外提个小细节:你把模板参数命名为A,和基类A重名了,这虽然语法合法,但极易造成混淆,建议改成T这类通用模板参数名,代码可读性会好很多。
解决办法
要实现你想要的多态效果,需要给所有X<T>(其中T继承自A)定义一个统一的非模板基类,让所有X<T>都继承自这个基类,这样不同的X<T>实例就可以通过这个共同基类的指针实现多态:
class A{ public: virtual ~A() = default; }; class B : public A{}; class C : public A{}; // 定义通用的非模板基类,作为所有X<T>的父类 class XBase { public: virtual ~XBase() = default; // 可以在这里声明所有X<T>需要的通用虚接口 }; template<typename T> class X : public XBase { public: virtual ~X() = default; // 这里可以添加和T相关的特化逻辑 }; class Y : public X<B>{}; class Z : public X<C>{}; int main(void) { XBase *test = new Y(); (void)test; return 0; }
这样Y继承自X<B>,而X<B>又继承自XBase,所以Y*可以隐式转换为XBase*,完美实现你想要的多态指针赋值效果。
内容的提问来源于stack exchange,提问作者poypoy
相关产品推荐
相关产品推荐

