C ++模板。不能使用继承的功能

时间:2013-09-13 00:54:10

标签: c++ templates inheritance casting explicit

这一直让我感到悲痛......

#include <iostream>

class InterfaceClass
{
    public:
    void test()
    {
        std::cout<<"Hello there.\n";
    }
};

template <class T>
class TemplateClass
{
    public:
    T t;
};

class TestClass: public InterfaceClass
{};

class TestInheritor
{
    public:
    TemplateClass < InterfaceClass >* templateInherit;
    InterfaceClass* normalInherit;

    void test()
    {
        normalInherit->test();
        templateInherit->t.test();
    }

};

int main (int nargs, char ** arg)
{

    TestInheritor ti;
    ti.normalInherit = new TestClass; // THIS ONE COMPILES OKAY.

    //ti.templateInherit = new TemplateClass <TestClass>; // COMPILE ERROR.

    // THIS WORKS THOUGH
    TemplateClass <TestClass> * tempClass = new TemplateClass <TestClass>;
    ti.templateInherit=(TemplateClass <InterfaceClass>*)tempClass; // WHY DO I HAVE TO EXPLICITLY CAST?

    // OUTPUT WORKS AS EXPECTED.
    ti.test();

    return 0;
}

正常的继承示例工作得很好。 TestClass自动转换为InterfaceClass。但是,使用模板示例,它会产生编译错误:

error: cannot convert 'TemplateClass<TestClass>*' to 'TemplateClass<InterfaceClass>*' in assignment

在我看来,很明显你可以将TemplateClass<TestClass>*转换为TemplateClass<InterfaceClass>* ......那么我在这里缺少什么?

我可以通过显式地将模板类转换为基类来修复它,我能够使用继承的test()函数而没有任何问题......那么为什么我需要显式地转换模板类?

很抱歉,如果这令人困惑......我很难解释这个问题。


好的,我更了解这个问题。我已决定将模板添加到TestInheritor,如下所示:

template <class T2>
class TestInheritor
{
    public:
    TemplateClass < T2 >* templateInherit;
    InterfaceClass* normalInherit;

    void test()
    {
        normalInherit->test();
        templateInherit->t.test();
    }
};

int main (int nargs, char ** arg)
{
    TestInheritor <TestClass> ti;
    ti.normalInherit = new TestClass;
    ti.templateInherit = new TemplateClass <TestClass>;
    ti.test();
    return 0;
}

可能不是完美的解决方案,但它适用于我的目的。


啊,我看到了你的解决方案:

#include <iostream>

class InterfaceClass
{
    public:
    void test()
    {
        std::cout<<"Hello there.\n";
    }
};

class TestClass: public InterfaceClass
{};



template <class T>
class TemplateClass
{
    public:
    T t;
};

template<>
class TemplateClass<TestClass> : public TemplateClass<InterfaceClass>
{
    public:
};


class TestInheritor
{
    public:
    TemplateClass < InterfaceClass >* templateInherit;
    InterfaceClass* normalInherit;

    void test()
    {
        normalInherit->test();
        templateInherit->t.test();
    }
};

int main (int nargs, char ** arg)
{
    TestInheritor ti;
    ti.normalInherit = new TestClass;
    ti.templateInherit = new TemplateClass <TestClass>;
    ti.test();
    return 0;
}

1 个答案:

答案 0 :(得分:0)

考虑

class Base
{};

class Derived : public Base
{};

template<typename T>
class TemplateClass
{};

与您的想法相反,TemplateClass<Derived> 在继承的过程中不是 TemplateClass<Base>,因此指向前者的指针不能隐式转换为指针后来。

那么为什么要显式地将指向TemplateClass<Derived>的指针转换为TemplateClass<Base>编译的指针?因为某个类型的任何指针都可以显式地转换为任何其他类型的任何指针,但无法保证转换有效!你也可以写一下

int* i = (int*) new TemplateClass<Derived>;

它会编译得很好,即使它显然是无效的转换。

现在为什么你的例子有效?纯粹的运气。此时,包含通过无效指针转换获得的地址的指针被取消引用,程序变为无效并且其行为未定义。任何事情都可能发生,包括做你期望的事情。

如果您希望TemplateClass<Derived> 在继承中成为 TemplateClass<Base>,您可以明确定义TemplateClass<>的专门化,明确说明此关系,例如以下内容:

template<>
class TemplateClass<Derived> : public TemplateClass<Base>
{};