0

好吧,这让我很伤心......

#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;
}
4

1 回答 1

0

考虑

class Base
{};

class Derived : public Base
{};

template<typename T>
class TemplateClass
{};

与您可能认为的相反,在继承的意义TemplateClass<Derived> 上不是 a TemplateClass<Base>,因此指向前者的指针不能隐式转换为后者的指针。

那么为什么要显式地将指针转换TemplateClass<Derived>TemplateClass<Base>编译指针呢?因为某种类型的任何指针都可以显式转换为任何其他类型的指针,但是不能保证转换是有效的!例如,您也可以编写

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

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

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

如果你想在继承的意义TemplateClass<Derived> 上成为一个 ,你可以定义一个明确说明这种关系的特化,如下所示:TemplateClass<Base>TemplateClass<>

template<>
class TemplateClass<Derived> : public TemplateClass<Base>
{};
于 2013-09-13T01:17:09.373 回答