メンバークラスT area
、T getArea()
、およびvoid setArea(T)
メンバー関数を持つテンプレートクラスArea
があるとします。
Area<int>
と入力することにより、特定のタイプのArea
オブジェクトを作成できます。
これで、Rectangle
クラスを継承するArea
クラスができました。 Rectangle
自体はテンプレートではないため、Rectangle<int>
と入力することはできません。
Area
オブジェクトの継承されたRectangle
タイプをどのように特化できますか?
編集:申し訳ありませんが、明確にするのを忘れました-私の質問は、エリアを特殊化せずに継承できるかどうかです。したがって、エリアのintとして継承されませんが、エリアレクタングルはタイプを特殊化できるためです。
テンプレートを理解するためには、用語を明確にすることが非常に有利です。なぜなら、テンプレートについて話す方法がテンプレートについて考える方法を決定するからです。
具体的には、Area
はテンプレートクラスではなく、クラステンプレートです。つまり、クラスを生成できるテンプレートです。 Area<int>
はそのようなクラスです(notオブジェクトですが、もちろん、他のクラスからオブジェクトを作成するのと同じ方法で、そのクラスからオブジェクトを作成できます)。別のそのようなクラスは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
が必要な場合があります(それ自体はAreaタイプを知る必要はありません)。テンプレートRectangle
をインスタンス化することで生成されるRectangle<T>
クラスは形式的に互いに独立しているため、そのようには機能しません。ただし、ここで複数の継承を利用できます。
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
};
Area<int>
から派生させようとしていますか?その場合、これを行います:
class Rectangle : public Area<int>
{
// ...
};
編集:明確化に続いて、実際にRectangle
もテンプレートにしようとしているようです。この場合、次のように動作します:
template <typename T>
class Rectangle : public Area<T>
{
// ...
};
Rectangleをテンプレートにして、タイプ名をAreaに渡します。
template <typename T>
class Rectangle : public Area<T>
{
};
class Rectangle : public Area<int> {
};
Rectangle
はテンプレートである必要があります。それ以外の場合は、1つのタイプのみです。そのベースは魔法のようですが、非テンプレートにすることはできません。 (そのベースはテンプレートインスタンス化かもしれませんが、ベースの機能を維持したいようですテンプレートとして。)
#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();
}