resueltos - relaciones entre clases c++
Heredar de una clase de plantilla en c++ (6)
Digamos que tenemos un Area
clase de plantilla, que tiene un miembro variable de T area
, un T getArea()
y un void setArea(T)
miembro funciones.
Puedo crear un objeto Area
de un tipo específico escribiendo Area<int>
.
Ahora tengo un Rectangle
clase que hereda la clase Area
. Como Rectangle
sí no es una plantilla, no puedo escribir Rectangle<int>
.
¿Cómo especializo el tipo de Area
heredado para objetos Rectangle
?
EDITAR: Perdón, me olvidé de aclarar: mi pregunta es si es posible heredar Área sin especializarla, por lo que no se hereda como Área de Ints, sino como Área Rectangular para la que se pueden especializar los tipos.
¿Estás tratando de derivar de Area<int>
? En ese caso, haz esto:
class Rectangle : public Area<int>
{
// ...
};
EDITAR: después de la aclaración, parece que en realidad estás tratando de hacer también una plantilla para Rectangle
, en cuyo caso debería funcionar lo siguiente:
template <typename T>
class Rectangle : public Area<T>
{
// ...
};
Haz que Rectangle sea una plantilla y pasa el nombre de tipo a Área:
template <typename T>
class Rectangle : public Area<T>
{
};
Para comprender las plantillas, es una gran ventaja tener la terminología correcta porque la forma en que hablas de ellas determina la manera de pensar sobre ellas.
Específicamente, Area
no es una clase de plantilla, sino una plantilla de clase. Es decir, es una plantilla a partir de la cual se pueden generar clases. Area<int>
es una clase (no es un objeto, pero por supuesto puede crear un objeto de esa clase de la misma manera que puede crear objetos de cualquier otra clase). Otra de esas clases sería Area<char>
. Tenga en cuenta que esas son clases completamente diferentes, que no tienen nada en común, excepto por el hecho de que se generaron a partir de la misma plantilla de clase.
Como Area
no es una clase, no puedes derivar la clase Rectangle
de ella. Solo puedes derivar una clase de otra clase (o varias de ellas). Como Area<int>
es una clase, podría, por ejemplo, derivar Rectangle
de ella:
class Rectangle:
public Area<int>
{
// ...
};
Como Area<int>
y Area<char>
son clases diferentes, puede incluso derivar de ambas al mismo tiempo (sin embargo, cuando acceda a miembros de ellas, tendrá que lidiar con ambigüedades):
class Rectangle:
public Area<int>,
public Area<char>
{
// ...
};
Sin embargo, debe especificar a qué clase pertenecer cuando defina Rectangle
. Esto es cierto independientemente de si esas clases se generan a partir de una plantilla o no. Dos objetos de la misma clase simplemente no pueden tener diferentes jerarquías de herencia.
Lo que puedes hacer es hacer que Rectangle
una plantilla. Si tú escribes
template<typename T> class Rectangle:
public Area<T>
{
// ...
};
Tiene una plantilla Rectangle
desde la que puede obtener una clase Rectangle<int>
que deriva de Area<int>
, y una clase diferente Rectangle<char>
que deriva de Area<char>
.
Es posible que desee tener un Rectangle
un solo tipo para poder pasar todo tipo de Rectangle
a la misma función (que no necesita conocer el tipo de área). Dado que las clases Rectangle<T>
generadas al crear instancias de la plantilla Rectangle
son formalmente independientes entre sí, no funciona de esa manera. Sin embargo, puede hacer uso de la herencia múltiple aquí:
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);
}
Si es importante que su Rectangle
genérico se derive de un Area
genérica Area
también puede hacer el mismo truco con 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
};
Rectangle
tendrá que ser una plantilla, de lo contrario, es solo un tipo . No puede ser una plantilla, mientras que su base es mágicamente. (Su base puede ser una instanciación de plantilla, aunque parezca querer mantener la funcionalidad de la base como plantilla ).
#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();
}
class Rectangle : public Area<int> {
};