web-dev-qa-db-ja.com

テンプレートクラス内で純粋な仮想メソッドを使用できますか?

以前は、これを行うことができないと確信していましたが、先日、いくつかのコードをいじくり回していて、コンパイルして動作しているように見えました。私はただ幸運になっていないことを確認したいだけです。テンプレートクラスに純粋な仮想関数を含めることはできますか?これは、デストラクタにとっても単なる仮想メソッドが有効であることを意味すると思いますか?

template <typename WordType> class DataSource
{
public:
    DataSource();
    DataSource(DataSource const& other);
    virtual ~DataSource();

    virtual void Put(
        WordType const* const data,
        unsigned int const wordCount) = 0;
}

私はそれをオンラインで調べてみましたが、見つけることができたのは、次のような通常のクラスで仮想メソッド(純粋またはそれ以外)を持つことができないことです:

class DataSource
{
public:
    DataSource();
    DataSource(DataSource const& other);
    virtual ~DataSource();

    template <typename WordType>
    virtual void Put(
        WordType const* const data,
        unsigned int const wordCount) = 0;
}

そして、これは、このメソッドがインスタンス化される可能性のあるすべての異なるタイプを参照する仮想テーブルを管理することができないためです。

ただし、テンプレートクラスの仮想メンバー関数については、テンプレートクラス変数がインスタンス化されると、クラス全体がテンプレートパラメータを介して「作成」されるため、異なるようです。この時点では、テンプレートの「検索と置換」の性質により、仮想メソッドはクラスの他の仮想メソッドとまったく同じです。

とにかく、そこで迷子になった場合に備えて質問を再度述べてください:仮想(純粋および/または通常の)仮想関数はtempateクラス内で許可されていますか?

43
Anthony

クラステンプレートには、実際に仮想関数または純粋仮想関数を含めることができます。これは、テンプレートとタイプリストを使用して訪問者パターンを実装するために、「モダンC++デザイン」でAndrei Alexandresuによって採用されました。あなたがコードを見ることができます ここで彼のLokiライブラリで 興味があるなら。

ほとんどの標準C++実装では、これは問題ありません。テンプレートがインスタンス化されると、仮想関数が単一の関数になるためです。その結果、vtableに必要なスロットの数は変換ユニット内で知ることができるため、vtableを生成できます。

前述したように、vtableスロットの数は変換単位内で認識されないため、仮想テンプレートメンバー関数を使用することはできません。

お役に立てれば!

52
templatetypedef

はい。完全に合法です。

.

8
jpalecek

テンプレートクラスとは何かを考えてください。それ自体はクラスではなく、コンパイラがクラスを作成するために使用できるテンプレートです。

そのため、テンプレートクラス定義に仮想関数(純粋またはそれ以外)を含めることができない理由はありません。それ自体は、仮想テーブルを含むコードを生成しないからです。

テンプレートクラスを実際にインスタンス化するとき、たとえばDataSource<int>、その後、コンパイラはその選択されたタイプの仮想テーブルのみを構築する必要があるため、テンプレート化されていないクラスの(純粋またはその他の)仮想関数と違いはありません。

7
JohnMcG

仮想関数を備えたクラステンプレートはまったく問題ありません。ただし、クラスまたはテンプレートクラスでプレフィックスが付いた仮想キーワードを持つテンプレート関数は許可されません。以下はあなたがそれを得るのに役立ちます:

//This is perfectly fine.
template <type T>
class myClass{
     virtual void function() = 0;
};

//This is NOT OK...
template<type T>
class myClass{
      template <type T>
      virtual void function() = 0;
};
3
Apte