Наследование от шаблонного класса в c ++ - PullRequest
89 голосов
/ 11 января 2012

Допустим, у нас есть шаблон класса Area, который имеет переменную-член T area, T getArea() и void setArea(T) функции-члена.

Я могу создать Area объект определенного типа, набрав Area<int>.

Теперь у меня есть класс Rectangle, который наследует класс Area. Поскольку Rectangle сам по себе не является шаблоном, я не могу набрать Rectangle<int>.

Как специализировать унаследованный тип Area для Rectangle объектов?

РЕДАКТИРОВАТЬ: Извините, я забыл уточнить - у меня есть вопросы, возможно ли наследовать Area без специализации, поэтому он не наследуется как Area ints, но как Area Rectangle может специализировать типы для.

Ответы [ 6 ]

202 голосов
/ 11 января 2012

Для понимания шаблонов огромное преимущество состоит в том, чтобы уточнить терминологию, потому что то, как вы говорите о них, определяет способ их восприятия.

В частности, Area - это не шаблонный класс, а шаблон класса. То есть это шаблон, из которого можно генерировать классы. Area<int> - это такой класс (это , а не объект, но, конечно, вы можете создать объект из этого класса так же, как вы можете создавать объекты из любого другого класса). Другой такой класс будет Area<char>. Обратите внимание, что это совершенно разные классы, которые не имеют ничего общего, за исключением того факта, что они были сгенерированы из одного и того же шаблона класса.

Поскольку Area не является классом, вы не можете извлечь класс Rectangle из него. Вы можете получить класс только из другого класса (или нескольких из них). Поскольку Area<int> является классом, вы можете, например, получить Rectangle из него:

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

Поскольку Area<int> и Area<char> - это разные классы, вы даже можете наследовать их от обоих одновременно (однако при доступе к их членам вам придется иметь дело с неясностями):

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

Однако при определении Rectangle вы должны указать, какие из них следует получить. Это верно независимо от того, генерируются ли эти классы из шаблона или нет. Два объекта одного класса просто не могут иметь разные иерархии наследования.

Что вы можете сделать, так это сделать Rectangle шаблоном. Если вы напишите

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

У вас есть шаблон Rectangle, из которого вы можете получить класс Rectangle<int>, производный от Area<int>, и другой класс Rectangle<char>, производный от Area<char>.

Возможно, вы хотите, чтобы у вас был один тип Rectangle, чтобы вы могли передавать все виды Rectangle в одну и ту же функцию (которая сама по себе не должна знать тип Area). Так как классы Rectangle<T>, сгенерированные путем создания экземпляра шаблона Rectangle, формально не зависят друг от друга, он не работает таким образом. Однако вы можете использовать множественное наследование здесь:

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

Если важно, чтобы ваш универсальный Rectangle был получен из универсального Area, вы можете проделать тот же трюк и с 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
};
16 голосов
/ 11 января 2012

Вы просто пытаетесь получить от Area<int>? В этом случае вы делаете это:

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

РЕДАКТИРОВАТЬ: После разъяснения, кажется, что вы на самом деле пытаетесь сделать Rectangle также шаблоном, и в этом случае должно работать следующее:

template <typename T>
class Rectangle : public Area<T>
{
    // ...
};
8 голосов
/ 11 января 2012

Сделать Rectangle шаблоном и передать имя типа в Area:

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

};
8 голосов
/ 11 января 2012
class Rectangle : public Area<int> {
};
6 голосов
/ 11 января 2012

Rectangle должен быть шаблоном, в противном случае это только один тип .Это не может быть не шаблон, в то время как его база волшебным образом.(Его основой может быть шаблон экземпляр , хотя вы, похоже, хотите сохранить функциональность базы как шаблон .)

0 голосов
/ 02 мая 2017
#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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...