0

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

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

但是,我不想将这种类型作为模板类传递,因为实用程序函数应该适用于任何具体的类变体,因为它们都可以将自己表示为 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

4 回答 4

1

virtualInterface2::ReturnSomeDouble()如果实例化了该类型或其子类型的对象,则函数(此处)不能保持未实现。
因为,当对象被实例化时,它需要vptr用函数的地址/定义填充隐藏的类成员virtual,没有找到,所以链接器错误。

您必须定义它们的主体或使其成为纯virtual函数(以便定义成为可选)。

于 2012-06-25T08:23:55.213 回答
0

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

(并且由于切片,您的代码正在调用未实现的基类函数。如果您将基类函数设为纯虚拟,那么您可能会收到更有用的错误消息)。

于 2012-06-25T08:23:52.557 回答
0

1 通过声明它们使接口函数成为纯虚拟的

virtual double ReturnSomeDouble() const = 0;

这样链接器就不会为基类寻找相应的函数。

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

于 2012-06-25T08:27:00.070 回答
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;
}

感谢所有帮助过的人。

于 2012-06-25T09:12:46.787 回答