0

ある場所で構築され、他の場所に渡されていくつかの操作を実行する、テンプレート化されたクラスの階層があります。

たとえば、クラスを double に変換する方法を知っている複雑なオブジェクトにテンプレート化することができ、テンプレート化されたクラスには、このオブジェクトを double として出力する操作があります。ユーティリティ関数の例は、このクラスのコレクションをテーブルとして出力する関数です。

ただし、この型をテンプレート化されたクラスとして渡したくありません。ユーティリティ関数は、すべての具象クラスのバリアントで機能する必要があるためです。これらはすべて double として表現できるからです。したがって、「represent as 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

virtual関数 (ここではInterface2::ReturnSomeDouble()) は、その型またはその子型のオブジェクトがインスタンス化されている場合、未実装のままにすることはできません。
オブジェクトがインスタンス化されると、非表示のクラス メンバーvptrに関数のアドレス/定義を入力する必要がvirtualあるため、見つからないため、リンカー エラーが発生します。

本体を定義するか、純粋なvirtual関数にする必要があります (その定義はオプションになります)。

于 2012-06-25T08:23:55.213 に答える
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 に答える
0

ここにあるのはスライスです。TClass2 のインスタンスは、変数 'myInterface' にコピーされると文字通りスライスされます (派生クラス部分は破棄されます)。ヒープ上で TClass2 をインスタンス化してから、'myInterface' をポインターまたは参照に変更して、これを機能させる必要があります。

(そして、スライスの結果として、コードは実装されていない基底クラス関数を呼び出しています。基底クラス関数を純粋仮想化した場合は、より役立つエラー メッセージが表示される可能性があります)。

于 2012-06-25T08:23:52.557 に答える