Para entender os modelos, é uma grande vantagem definir a terminologia correta, porque a maneira como você fala sobre eles determina a maneira de pensar sobre eles.
Especificamente, Areanão é uma classe de modelo, mas um modelo de classe. Ou seja, é um modelo a partir do qual as classes podem ser geradas. Area<int>é tal classe um (é não um objeto, mas é claro que você pode criar um objeto dessa classe da mesma forma que você pode criar objetos a partir de qualquer outra classe). Outra classe seria Area<char>. Observe que essas são classes completamente diferentes, que não têm nada em comum, exceto pelo fato de que foram geradas a partir do mesmo modelo de classe.
Como Areanão é uma classe, você não pode derivar a classe Rectangledela. Você só pode derivar uma classe de outra classe (ou de várias delas). Como Area<int>é uma classe, você poderia, por exemplo, derivar Rectangledela:
class Rectangle:
public Area<int>
{
// ...
};
Como Area<int>e Area<char>são classes diferentes, você pode até derivar de ambas ao mesmo tempo (no entanto, ao acessar membros delas, você terá que lidar com ambigüidades):
class Rectangle:
public Area<int>,
public Area<char>
{
// ...
};
No entanto, você deve especificar de qual classe derivar ao definir Rectangle. Isso é verdade, não importa se essas classes são geradas a partir de um modelo ou não. Dois objetos da mesma classe simplesmente não podem ter hierarquias de herança diferentes.
O que você pode fazer é criar Rectangleum modelo também. Se você escrever
template<typename T> class Rectangle:
public Area<T>
{
// ...
};
Você tem um modelo Rectangledo qual pode obter uma classe Rectangle<int>que deriva de Area<int>e uma classe diferente Rectangle<char>que deriva Area<char>.
Pode ser que você queira ter um único tipo Rectangle para que possa passar todos os tipos de Rectanglepara a mesma função (que por si só não precisa saber o tipo de Área). Como as Rectangle<T>classes geradas pela instanciação do modelo Rectanglesão formalmente independentes umas das outras, isso não funciona. No entanto, você pode usar a herança múltipla aqui:
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);
}
Se for importante que o seu genérico Rectangleseja derivado de um genérico, Areavocê também pode fazer o mesmo com 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
};