1

いくつかのメソッドが型固有であるクラス テンプレートがあるとします。

template <typename T>
class Shape
{
...
void Foo();
...
};

ここで、たとえば次を使用して、型固有の関数を特殊化します。

void Shape<bool>::Foo() {...};
void Shape<double>::Foo() {...};

質問:

  1. 型に応じて Foo に異なるパラメーターが必要な場合はどうなりますか? クラス宣言のパラメーターとは異なるパラメーターを使用して、特定の型のメソッドを特殊化することは可能ですか? 許可されていないと思うのですが、どうすればいいですか?

  2. Foo が定義されていない型のクラスのインスタンス化を防ぐ方法は?

  3. 私が説明した状況とは対照的に、仮想関数と純粋仮想関数をいつ使用する必要がありますか? テンプレートと継承の両方を混在させることはできますか?

4

2 に答える 2

0

(1) ある種、しかし、あなたがやろうとしている方法とはまったく異なります。基本的に、特殊化で関数を定義する必要があります。基本クラスと派生クラスを宣言するときとはかなり異なります。

template <typename T> class Shape {
    static_assert(false, "Not implemented");
};

template <> class Shape<bool> {
    void Foo(bool a, std::string b) {...}
};

template <> class Shape<int> {
    void Foo(int, std::string, whatever else) {...}
};

特殊化されていない元の Shape で Foo を定義したとしても、特殊化には影響しません。完全な専門化は元のテンプレートを拡張するのではなく、元のテンプレートを置き換えます!

(2) static_assert を使用します。上記の例を参照してください。

(3) はい、テンプレートと継承を混在させることができます。仮想関数のランタイム ポリモーフィズムと静的ポリモーフィズム。テンプレート パラメーターはコンパイル時に認識されている必要がありますが、ランタイム ポリモーフィック オブジェクトの正確な型は認識されていません。これらは基本クラスの参照によって参照される可能性があるためです。上記のテンプレート化された例では、単純に言うことはできません

template <class T> Shape {...};

...

Shape* myShape;   // Compiler error: Shape requires a template parameter

ただし、継承を使用すると、次のことができます。

class ShapeBase { virtual void Foo() = 0; };
class Circle : public ShapeBase { virtual void Foo() { ... } };
class Square : public ShapeBase { virtual void Foo() { ... } };
...

Shape* myShape = new Circle;
myShape->Foo(); // calls Circle->Foo()

継承を使用する場合は、関数のシグネチャが一致する必要があることに注意してください。これは、実行時まで決定を延期するために支払う代償です。

于 2013-04-16T20:50:23.463 に答える