Heredar de una clase de plantilla en c++


Digamos que tenemos una clase de plantilla Area, que tiene una variable miembro T area, una T getArea() y una void setArea(T) funciones miembro.

Puedo crear un objeto Area de un tipo específico escribiendo Area<int>.

Ahora tengo una clase Rectangle que hereda la clase Area. Dado que Rectangle en sí no es una plantilla, no puedo escribir Rectangle<int>.

¿Cómo especializo el tipo Area heredado para los objetos Rectangle?

EDITAR: Lo siento, me olvidé de aclarar - mis preguntas es si es posible hereda el área sin especializarla, por lo que no se hereda como Área de ints sino como Área Rectangular que puede especializar los tipos para.

Author: dtech, 2012-01-11

6 answers

Para entender las plantillas, es una gran ventaja obtener la terminología correcta porque la forma en que hablas de ellas determina la forma 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 tal clase (es no un objeto, pero por supuesto puede crear un objeto de esa clase de la misma manera que puede crear objetos de cualquier otra clase). Otro la clase sería Area<char>. Tenga en cuenta que 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.

Puesto que Area no es una clase, no se puede derivar la clase Rectangle de ella. Solo puede derivar una clase de otra clase (o varias de ellas). Dado que Area<int> es una clase, podrías, por ejemplo, derivar Rectangle de ella:

class Rectangle:
  public Area<int>
{
  // ...
};

Dado que Area<int> y Area<char> son clases diferentes, incluso puede derivar de ambas en al mismo tiempo (sin embargo, al acceder a los miembros de ellos, tendrá que lidiar con ambigüedades):

class Rectangle:
  public Area<int>,
  public Area<char>
{
  // ...
};

Sin embargo, debe especificar de qué clase derivar cuando defina Rectangle. Esto es cierto sin importar 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 Rectangle una plantilla también. Si escribes

template<typename T> class Rectangle:
  public Area<T>
{
  // ...
};

Tiene una plantilla Rectangle de la que puedes obtener una clase Rectangle<int> que deriva de Area<int>, y una clase diferente Rectangle<char> que deriva de Area<char>.

Puede ser que desee tener un solo tipo Rectangle para que pueda pasar todo tipo de Rectangle a la misma función (que en sí misma no necesita saber el tipo de Área). Dado que las clases Rectangle<T> generadas al instanciar 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 tu genérico Rectangle se derive de un genérico Area también puedes 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
};
 167
Author: celtschk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-10 21:16:49

¿Estás tratando de derivar de Area<int>? En cuyo caso usted hace esto:

class Rectangle : public Area<int>
{
    // ...
};

EDITAR: Después de la aclaración, parece que en realidad estás tratando de hacer Rectangle una plantilla también, en cuyo caso lo siguiente debería funcionar:

template <typename T>
class Rectangle : public Area<T>
{
    // ...
};
 13
Author: Stuart Golodetz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-10 22:43:40
class Rectangle : public Area<int> {
};
 8
Author: ldanko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-10 20:46:27

Rectangle tendrá que ser una plantilla, de lo contrario es solo un tipo. No puede ser una no-plantilla mientras que su base mágicamente lo es. (Su base puede ser una plantilla instanciación, aunque parece querer mantener la funcionalidad de la base como una plantilla.)

 6
Author: Lightness Races in Orbit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-10 20:44:24

Haga de Rectangle una plantilla y pase el nombre del tipo a Área:

template <typename T>
class Rectangle : public Area<T>
{

};
 6
Author: pezcode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-10 22:44:13
#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();
}
 0
Author: Narendra kumawat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-21 17:32:21