テンプレートを理解する上で、用語をわかりやすくすることは、テンプレートについて話す方法がテンプレートの考え方を決定するため、非常に有利です。
具体的に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
がジェネリックから派生していることが重要な場合は、次の方法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
};