对于理解模板而言,直接理解术语具有巨大的优势,因为您谈论模板的方式决定了思考模板的方式。
具体来说,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
。不管这些类是否从模板生成,都是如此。同一类的两个对象不能简单地具有不同的继承层次结构。
您可以做的就是制作Rectangle
一个模板。如果你写
template<typename T> class Rectangle:
public Area<T>
{
// ...
};
您有一个模板Rectangle
,可以从中获取一个类Rectangle<int>
,该类从派生Area<int>
,而另一个类Rectangle<char>
从派生Area<char>
。
可能是您希望有一个单一类型,Rectangle
以便可以将各种形式传递Rectangle
给同一个函数(它本身不需要知道Area类型)。由于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
};