1. ホーム
  2. c++

[解決済み] c++のテンプレートクラスからの継承

2022-08-25 23:19:55

質問

例えば、テンプレートクラス Area があり、その中にメンバ変数 T area , a T getArea()void setArea(T) のメンバー関数があります。

を作ることができます。 Area と入力することで、特定の型のオブジェクトを作成できます。 Area<int> .

これで、クラス Rectangle を継承した Area クラスを継承する このため Rectangle 自体はテンプレートではないので、私は Rectangle<int> .

どのようにすれば、継承された Area の型を Rectangle オブジェクトを作成できますか?

EDIT: すみません、明確にするのを忘れていました - 私の質問は、それを特殊化せずに面積を継承することが可能であるかどうかということです。

どのように解決するのですか?

テンプレートを理解するためには、用語を整理しておくことが非常に有利です。なぜなら、テンプレートの話し方によって、テンプレートについての考え方が決まるからです。

具体的には Area はテンプレート・クラスではなく、クラス・テンプレートです。つまり、クラスを生成するためのテンプレートです。 Area<int> はそのようなクラスです(それは ではなく ではありませんが、もちろん他のクラスからオブジェクトを作成するのと同じ方法で、そのクラスからオブジェクトを作成することができます)。もう一つのそのようなクラスは Area<char> . これらは完全に異なるクラスであり、同じクラステンプレートから生成されたという事実以外には何も共通点がないことに注意してください。

から Area はクラスではないので、クラス Rectangle を派生させることはできません。クラスを派生させることができるのは、他のクラス(または複数のクラス)だけです。ですから Area<int> はクラスなので、たとえば Rectangle を派生させることができます。

class Rectangle:
  public Area<int>
{
  // ...
};

以降 Area<int> であり Area<char> は異なるクラスであり、同時に両方から派生することもできます(ただし、それらのメンバにアクセスする際には、曖昧さに対処する必要があります)。

class Rectangle:
  public Area<int>,
  public Area<char>
{
  // ...
};

を定義する際に、どのクラスから派生させるかを指定する必要があります。 Rectangle . これは、これらのクラスがテンプレートから生成されたものであるかどうかに関係なく、当てはまります。同じクラスの2つのオブジェクトは、単に異なる継承階層を持つことはできません。

あなたができることは Rectangle もテンプレートにすることです。もし、あなたが

template<typename T> class Rectangle:
  public Area<T>
{
  // ...
};

あなたは、テンプレート Rectangle を取得し、そこからクラス Rectangle<int> から派生した Area<int> と、別のクラス Rectangle<char> から派生した Area<char> .

を1つの型にしたい場合があります。 Rectangle を渡せるように、あらゆる種類の Rectangle を同じ関数に渡すことができます (関数自身はエリアの型を知る必要はありません)。そのため Rectangle<T> クラスをインスタンス化することによって生成されるので、 テンプレート Rectangle は形式的には互いに独立していますが、そのようには動作しません。しかし、ここでは多重継承を利用することができます。

class Rectangle // not inheriting from any Area type
{
  // Area independent interface
};

template<typename T> class SpecificRectangle:
  public Rectangle,
  public Area<T>
{
  // Area dependent stuff
};

void foo(Rectangle&); // A function which works with generic rectangles

int main()
{
  SpecificRectangle<int> intrect;
  foo(intrect);

  SpecificRectangle<char> charrect;
  foo(charrect);
}

もし、一般的な Rectangle が一般的な Area を使用すると、同じトリックを Area でも同じことができます。

class Area
{
  // generic Area interface
};

class Rectangle:
  public virtual Area // virtual because of "diamond inheritance"
{
  // generic rectangle interface
};

template<typename T> class SpecificArea:
  public virtual Area
{
  // specific implementation of Area for type T
};

template<typename T> class SpecificRectangle:
  public Rectangle, // maybe this should be virtual as well, in case the hierarchy is extended later
  public SpecificArea<T> // no virtual inheritance needed here
{
  // specific implementation of Rectangle for type T
};