模板多态不工作?

时间:2009-08-17 17:00:12

标签: c++ templates polymorphism

我正在构建一个小模板层次结构并尝试使用类多态。下面是一些示例代码(无法编译)来演示它:

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) {}
};

这个问题有什么“好”的解决方案吗?

2 个答案:

答案 0 :(得分:4)

首先,这个:

C       == B<int>
B<int>  == B<T>

错了。正确的形式是:

  

C来自B<int>

     

B<int>B<T>

的实例化

这完全是另一回事。现在,转向问题的关键。

C ++模板不是变体。特别是,给定两个类BaseDerived以及类模板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) {}
};

然而,问题太抽象了,无法提供解决方案......