我正在构建一个小模板层次结构并尝试使用类多态。下面是一些示例代码(无法编译)来演示它:
template<typename T>
struct A
{};
template<typename T>
struct B
{
B (A<B> *) {}
};
struct C : public B<int>
{
C(A<C> *p) : B<int>(p) {} // error
};
int main() {
A<C> ac;
C c(&ac);
}
我的编译器(OS X上的gcc 4.01)在指定的行上抛出以下错误:
error: no matching function for call to ‘B<int>::B(A<C>*&)’
但是根据我的逻辑假设,代码应该有效,因为
C == B<int>
B<int> == B<T>
=> A<C> == A<B<T> >
有人可以指出我的错误在哪里以及如何解决它吗?
答案似乎是我的问题无法通过常规继承树来解决,因为模板是静态的以识别多态性。施放 A&lt;是否合法? C&gt; 到 A&lt; B&lt; int&gt; &gt; 强制多态,虽然从设计的角度来看它很可怕?
struct C : public B<int>
{
C(A<C> *p) : B<int>((A<B<int> > *)p) {}
};
这个问题有什么“好”的解决方案吗?
答案 0 :(得分:4)
首先,这个:
C == B<int>
B<int> == B<T>
错了。正确的形式是:
C
来自B<int>
的实例化
B<int>
是B<T>
这完全是另一回事。现在,转向问题的关键。
C ++模板不是变体。特别是,给定两个类Base
和Derived
以及类模板Foo<T>
,Foo<Derived>
不是Foo<Base>
的子类,而是指向前者的指针和引用不可兑换成后者。这样做的理由是这样做并不总是类型安全的。例如,假设它是可能的,并且std::list<Derived>&
可以转换为std::list<Base>&
。如果是这样,我可以写:
struct Base {...};
struct Derived1 : Base {...};
struct Derived2 : Base {...};
std::list<Derived1> dl;
std::list<Base>& bl = dl;
bl.push_back(Derived2()); // dl is a list of Derived1, but we just put
// an instance of Derived2 into it...
所以这是非法的(并且允许它也存在实施问题)。此外,也无法选择C ++模板的方差。每个模板实例化只是一个不同的类,其基类只是定义中基类列表中特别列出的那些类。它与同一类模板的其他实例没有特殊关系。
因此,在您的情况下,A<B<int>>
与A<C>
的类型不同,它们之间也没有任何隐式(或有意义的显式)指针转换。
答案 1 :(得分:3)
A&lt; B&lt; int&gt; &GT;与A&lt;的类型不同C>,即使C来自B&lt; int&gt;。
构造函数C的参数,类型A&lt; C> *与构造函数B所请求的参数不相容<&lt; int&gt;,即A&lt; B&lt; INT&GT; &GT;
稍后编辑: 使用模板化构造函数:
template<typename T>
struct B
{
template< typename E>
B (E *) {}
};
struct C : public B<int>
{
template< typename E>
C(E *p) : B<int>(p) {}
};
然而,问题太抽象了,无法提供解决方案......