模板化类c ++的非模板化接口

时间:2012-06-25 08:18:47

标签: c++ templates inheritance linker-errors

我有一个模板化类的层次结构,它们在一个地方构建并传递到其他地方以对它们进行一些操作。

例如,一个类可以模板化为一些知道如何将自身转换为double的复杂对象,并且模板化类具有将该对象输出为double的操作。效用函数的一个示例是将此类的集合作为表输出的函数。

但是,我不想将此类型作为模板化类传递,因为效用函数应该适用于任何具体的类变体,因为它们都可以表示为double。因此,我想要一些具有'表示为双精度'功能的非模板化接口。为什么以下不起作用?

#include "stdafx.h"

class Interface1
{
public:
    virtual int ReturnSomeInt();
};

template<typename myType>
class TClass1 : public Interface1
{
public:
    int ReturnSomeInt() {return 5;}
    void CalculateSomething(myType myValue) {}

    TClass1() {}
};

//---------------------------------------------

class Interface2 : public Interface1
{
public:
    virtual double ReturnSomeDouble();
};

template<typename myType>
class TClass2 : public TClass1<myType>, public Interface2
{
public:
    double ReturnSomeDouble() {return 9.2;}
    void CalculateSomethingElse(myType myValue) {}

    TClass2() {}
};

//---------------------------------------------

int _tmain(int argc, _TCHAR* argv[])
{
    Interface2 myInterface = TClass2<float>();
    int myInt = myInterface.ReturnSomeInt();
    double myDouble = myInterface.ReturnSomeDouble();
    return 0;
}

我收到2019年的链接错误,指出它无法找到符号Interface2::ReturnSomeDouble(void)。可能是什么问题?

4 个答案:

答案 0 :(得分:1)

如果实例化该类型的对象或其子类型,则

virtual函数(此处为Interface2::ReturnSomeDouble())不能保持未实现。
因为,当对象被实例化时,它需要使用vptr函数的地址/定义填充隐藏的类成员virtual,这是找不到的,因此链接器错误。

您必须定义自己的身体或使其成为纯virtual函数(以便定义成为可选项)。

答案 1 :(得分:0)

这里有slicing。当你复制到变量'myInterface'时,你的TClass2实例已被字面切片(派生类部分已被丢弃)。您需要在堆上实例化TClass2,然后将“myInterface”更改为指针或引用以使其工作。

(作为切片的结果,你的代码正在调用未实现的基类函数。如果你要使基类函数纯虚拟,那么你可能得到了一个更有用的错误信息。)

答案 2 :(得分:0)

1通过声明接口函数使其纯虚拟

virtual double ReturnSomeDouble() const = 0;

以便链接器不会查找基类的相应函数。

2声明interface1是一个虚拟基础,以避免在Tclass2中继承它两次,尽管这对你的代码编译并不重要

答案 3 :(得分:0)

由于我的问题有很多好的答案,我决定重新发布我的代码并实施所有有用的评论。

#include "stdafx.h"

class Interface1
{
public:
    virtual int ReturnSomeInt()=0;
};

template<typename myType>
class TClass1 : public Interface1
{
public:
    int ReturnSomeInt() {return 5;}
    void CalculateSomething(myType myValue) {}

    TClass1() {}
};

//---------------------------------------------

class Interface2 : public Interface1
{
public:
    virtual double ReturnSomeDouble()=0;
};

template<typename myType>
class TClass2 : public TClass1<myType>, public Interface2
{
public:
    int ReturnSomeInt() { return TClass1<myType>::ReturnSomeInt(); }
    double ReturnSomeDouble() {return 9.2;}
    void CalculateSomethingElse(myType myValue) {}

    TClass2() {}
};

//---------------------------------------------

void WriteClassToConsole(Interface2& myInterface)
{
    std::cout << "My int:\t" << myInterface.ReturnSomeInt() << std::endl;
    std::cout << "My dbl:\t" << myInterface.ReturnSomeDouble() << std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
    TClass2<float> myClass;
    WriteClassToConsole(myClass);
    std::getchar();
    return 0;
}

感谢所有帮助过的人。