簡體   English   中英

非模板化類的接口c ++

[英]non templated interfaces to templated classes c++

我有一個模板化類的層次結構,這些模板化類在一個地方構造並傳遞到其他地方以對它們進行一些操作。

例如,可以將一個類模板化為某個復雜的對象,該對象知道如何將其自身轉換為double型,並且該模板化的類具有將該對象輸出為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) 可能是什么問題呢?

如果實例化了該類型的對象或其子類型,則virtual函數(此處為Interface2::ReturnSomeDouble() )不能保持未實現。
因為,當實例化對象時,它需要使用未找到的virtual函數的地址/定義填充隱藏的類成員vptr ,從而導致鏈接器錯誤。

您要么必須定義它們的主體,要么使其成為純virtual函數(這樣定義就成為可選的)。

您在這里正在切片 當您將TClass2實例復制到變量“ myInterface”(派生的類部分已被丟棄)時,實際上已經對其進行了切片。 您需要在堆上實例化TClass2,然后將“ myInterface”更改為指針或引用才能使其正常工作。

(作為切片的結果,您的代碼正在調用未實現的基類函數。如果您要使基類函數成為純虛擬的,則可能會得到一條更有用的錯誤消息)。

1通過聲明接口函數使其成為純虛函數

virtual double ReturnSomeDouble() const = 0;

這樣鏈接器就不會為基類尋找相應的函數。

2將interface1聲明為虛擬基礎,以避免在Tclass2繼承兩次,盡管這對於您的代碼進行編譯並不重要

由於我的問題有很多好的答案,因此我決定重新發布代碼,並實施所有有用的注釋。

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

感謝所有提供幫助的人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM