2012-01-10 26 views
52

Digamos que tenemos una clase de plantilla Area, que tiene una variable de miembro T area, una T getArea() y una void setArea(T) funciones de miembro. Puede crear un objeto Area de un tipo específico escribiendo Area<int>.Heredando de una clase de plantilla en C++

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: 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 Rectángulo de área puede especializar los tipos.

+1

Es una "plantilla de clase" porque es una plantilla a partir de la cual se generan las clases. – sbi

Respuesta

138

para la comprensión de las plantillas, es de gran ventaja para conseguir la terminología recta debido a su forma de hablar acerca de t el dobladillo determina la manera de pensar sobre ellos.

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 (es no 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.

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

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

Desde Area<int> y Area<char> distintas clases, incluso se puede derivar de ambos en el mismo tiempo (sin embargo, cuando se accede a los miembros de ellas, que tendrá que hacer frente a las ambigüedades):

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

Sin embargo, usted tiene que especificar cuál clasifica para derivar a partir de cuando se define 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 también una plantilla en Rectangle. Si se escribe

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

tiene una plantilla Rectangle a partir del cual se puede obtener una clase que deriva de Rectangle<int>Area<int>, y una clase diferente Rectangle<char> que se deriva de Area<char>.

Puede ser que desee tener un solo tipo Rectangle para poder pasar todo tipo de Rectangle a la misma función (que no necesita conocer el tipo de área). Como las clases Rectangle<T> generadas al crear instancias de la plantilla Rectangle son formalmente independientes entre sí, no funciona de esa manera. Sin embargo, usted 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 genérico Rectangle se deriva de un genérico Area que puede hacer el mismo truco con Area también:

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 
}; 
4

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 de instancias de plantilla , aunque parece que quieres para mantener la funcionalidad de la base como plantilla .)

7
class Rectangle : public Area<int> { 
}; 
10

simplemente estás tratando de derivar de Area<int>? En cuyo caso se hace esto:

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

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

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

hacer una plantilla rectangular y pasar el nombre de tipo de hasta Área:

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

}; 
0
#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

¿y si tuvieras métodos en la clase derivada? ¿Cómo los definirías? Y aún más importante, al menos para mí, ¿cómo llamas/usas esos métodos en tu función main()? – Pototo

+0

La respuesta a su pregunta está en el código –

+2

Primero, esta es una pregunta muy antigua que ya tiene una gran respuesta. En segundo lugar, evite las respuestas (y las preguntas) que son solo códigos. También es útil incluir explicaciones detalladas. – marcman

Cuestiones relacionadas