web-dev-qa-db-fra.com

Héritage d'une classe de modèle en c ++

Disons que nous avons un modèle de classe Area, qui a une variable membre T area, Une T getArea() et une void setArea(T) fonctions membres.

Je peux créer un objet Area d'un type spécifique en tapant Area<int>.

Maintenant, j'ai une classe Rectangle qui hérite de la classe Area. Puisque Rectangle n'est pas un modèle, je ne peux pas taper Rectangle<int>.

Comment spécialiser le type hérité Area pour les objets Rectangle?

EDIT: Désolé, j'ai oublié de clarifier - ma question est de savoir s'il est possible d'hériter de Area sans le spécialiser, de sorte qu'il ne soit pas hérité en tant que Area of ​​ints mais en tant que Area Rectangle peut en spécialiser les types.

89
dtech

Pour comprendre les modèles, il est extrêmement avantageux de bien comprendre la terminologie, car la façon dont vous en parlez détermine la manière de les considérer.

Plus précisément, Area n'est pas une classe de modèle, mais un modèle de classe. C'est un modèle à partir duquel les classes peuvent être générées. Area<int> est une telle classe (c'est pas un objet, mais vous pouvez bien entendu créer un objet à partir de cette classe de la même manière que vous pouvez créer des objets à partir de toute autre classe). Une autre classe de ce type serait Area<char>. Notez que ce sont des classes complètement différentes, qui n'ont rien en commun si ce n'est qu'elles ont été générées à partir du même modèle de classe.

Puisque Area n'est pas une classe, vous ne pouvez pas en dériver la classe Rectangle. Vous pouvez uniquement dériver une classe d'une autre classe (ou de plusieurs d'entre elles). Puisque Area<int> _ est une classe, vous pouvez, par exemple, en tirer Rectangle:

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

Puisque Area<int> et Area<char> sont différentes classes, vous pouvez même dériver des deux en même temps (cependant, lorsque vous accédez à leurs membres, vous devrez faire face à des ambiguïtés):

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

Cependant, vous devez spécifier de quelle classe dériver lorsque vous définissez Rectangle. Cela est vrai, que ces classes soient générées à partir d'un modèle ou non. Deux objets de la même classe ne peuvent tout simplement pas avoir des hiérarchies d'héritage différentes.

Ce que vous pouvez faire est de faire de Rectangle un modèle également. Si vous écrivez

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

Vous avez un template Rectangle à partir duquel vous pouvez obtenir une classe Rectangle<int> qui provient de Area<int>, et une classe différente Rectangle<char> qui provient de Area<char>.

Il se peut que vous souhaitiez avoir un seul type Rectangle afin de pouvoir passer toutes sortes de Rectangle à la même fonction (qui n'a pas besoin de connaître le type Area). Depuis le Rectangle<T> Les classes générées en instanciant le modèle Rectangle sont formellement indépendantes les unes des autres, cela ne fonctionne pas ainsi. Cependant, vous pouvez utiliser plusieurs héritages ici:

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

S'il est important que votre générique Rectangle soit dérivé d'un générique Area, vous pouvez faire la même chose avec 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
};
206
celtschk

Est-ce que vous essayez juste de dériver de Area<int>? Dans ce cas, vous faites ceci:

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

EDIT: Après la clarification, il semble que vous essayiez réellement de créer Rectangle un modèle également, auquel cas les éléments suivants devraient fonctionner:

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

Faites de Rectangle un gabarit et transmettez le nom de type à la zone:

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

};
8
pezcode
class Rectangle : public Area<int> {
};
8
ldanko

Rectangle devra être un modèle, sinon n seul type. Ce ne peut pas être un non-modèle alors que sa base est comme par magie. (Sa base peut être un modèle instanciation, bien que vous sembliez vouloir conserver les fonctionnalités de la base en tant que modèle.)

6
#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