【问题标题】:C++ Templates. Can't use inherited functionC++ 模板。不能使用继承函数
【发布时间】:2013-09-13 00:54:10
【问题描述】:

这让我很伤心......

#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&lt;TestClass&gt;* 转换为TemplateClass&lt;InterfaceClass&gt;*...那么我在这里缺少什么?

我可以通过将模板类显式转换为基类来修复它,我可以毫无问题地使用继承的 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;
}

【问题讨论】:

    标签: c++ templates inheritance casting explicit


    【解决方案1】:

    考虑

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

    与你可能想的相反,TemplateClass&lt;Derived&gt; 不是TemplateClass&lt;Base&gt; 在继承的意义上,所以指向前者的指针不能隐式转换为后者的指针。

    那么为什么将指向TemplateClass&lt;Derived&gt; 的指针显式转换为TemplateClass&lt;Base&gt; 的指针会编译?因为任何特定类型的指针都可以显式转换为任何其他类型的指针,但是不能保证转换是有效的!例如,您也可以编写

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

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

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

    如果您希望TemplateClass&lt;Derived&gt; 在继承方面成为 TemplateClass&lt;Base&gt;,您可以定义TemplateClass&lt;&gt; 的特化,明确说明这种关系,如下所示:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-21
      • 2021-04-20
      • 1970-01-01
      • 2021-10-17
      • 1970-01-01
      • 2011-04-17
      • 1970-01-01
      • 2018-09-29
      相关资源
      最近更新 更多