C ++のテンプレートクラスから継承する


106

テンプレートクラスAreaがあり、メンバー変数T area、a T getArea()void setArea(T)メンバー関数があるとします。

Area入力して、特定のタイプのオブジェクトを作成できますArea<int>

これで、クラスRectangleを継承するAreaクラスができました。それRectangle自体はテンプレートではないので、と入力できませんRectangle<int>

オブジェクトの継承Areaタイプをどのように特化しRectangleますか?

編集:申し訳ありませんが、明確にするのを忘れていました-私の質問は、エリアを特殊化せずに継承できるかどうかです。そのため、エリアは整数のエリアとして継承されませんが、エリア長方形はタイプを特殊化できます。


3
これはクラステンプレートです。これは、クラスが生成されるテンプレートだからです。
sbi

1
@sbiここで炎の戦争を始めるつもりはありませんが、Bjarne Stroustrupがクラステンプレートテンプレートクラスを区別しない場合(C ++プログラミング言語、第4版、セクション23.2.1を参照)、その後、どちらでもない。
Michael Warner

@MichaelWarner私が彼を区別したことを覚えているようです。それはUsenetでは90年代でした。たぶん彼はあきらめました。(または、多分彼はインスタンス化されたクラステンプレートをテンプレートクラスと
呼んでい

回答:


244

テンプレートを理解する上で、用語をわかりやすくすることは、テンプレートについて話す方法がテンプレートの考え方を決定するため、非常に有利です。

具体的に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>

同じ関数に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がジェネリックから派生していることが重要な場合は、次の方法AreaAreaも同じトリックを実行できます。

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

注:テンプレートタイプパラメータは、そのクラステンプレートをインスタンス化するオブジェクトのクラスの一部です。つまり、これはクラスのコンポーネントではなく、型の一部です。
ニコス

21

あなただけから派生しようとしていますArea<int>か?その場合は、次のようにします。

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

編集:説明に従って、あなたも実際にRectangleテンプレートを作成しようとしているようですが、その場合は以下が機能するはずです:

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


8

Rectangleをテンプレートにして、型名をAreaに渡します。

template <typename T>
class Rectangle : public Area<T>
{

};

6

Rectangleテンプレートにする必要があります。それ以外の場合は、1つのタイプにすぎません。そのベースが魔法のようにある間、それは非テンプレートであってはなりません。(そのベースはテンプレートのインスタンス化である可能性がありますが、ベースの機能をテンプレートとして維持したいようです。)


3
#include<iostream>

using namespace std;

template<class t> 
class base {
protected:
    t a;
public:
    base(t aa){
        a = aa;
        cout<<"base "<<a<<endl;
    }
};

template <class t> 
class derived: public base<t>{
    public:
        derived(t a): base<t>(a) {
        }
        //Here is the method in derived class 
    void sampleMethod() {
        cout<<"In sample Method"<<endl;
    }
};

int main() {
    derived<int> q(1);
    // calling the methods
    q.sampleMethod();
}

派生クラスにメソッドがある場合はどうなりますか?それらをどのように定義しますか?そして、ほとんどの場合、少なくとも私にとっては、これらのメソッドをmain()関数でどのように呼び出し/使用するのでしょうか。
Pototo

6
まず、これは本当に古い質問ですが、すでに素晴らしい答えがあります。第二に、コードのみの回答(および質問)を避けてください。詳細な説明も含めると便利です。
marcman 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.