2017-02-12 16 views
3

Я хочу создать шаблон абстрактного класса, заставив все экземпляры реализовать функцию doStuff с использованием чистой виртуальной функции.Реализация чистых виртуальных функций из класса шаблонов - типы параметров

У меня есть следующий шаблон:

template<class T> 
class X 
{ 
    public: 
     X() {}; 
     virtual ~X() {}; 
     virtual X<T>& doStuff(X<T>& x) = 0; 
}; 

и экземпляр с T = INT:

class Y : public X<int> 
{ 
    public: 
     Y(); 
     virtual ~Y(); 
     Y& doStuff(Y& x) { 
      Y res; 
      Y& res2 = res; 
      return res2; 
     } 
}; 

Я получаю сообщение об ошибке:

В функции члена «Y & Y :: doStuff (Y &) ': не может объявить переменную' res 'для абстрактный тип «Y», поскольку следующие виртуальные функции являются чистыми в пределах «Y»: Х Х & :: DoStuff (Х &) [с Т = INT]

Если я изменить тип аргумента к DoStuff в Y, все в порядке:

class Y : public X<int> 
{ 
    public: 
     Y(); 
     virtual ~Y(); 
     Y& doStuff(X<int>& x) { 
      Y res; 
      Y& res2 = res; 
      return res2; 
     } 
}; 

Почему параметр не является ссылкой на объект Y, если Y реализует X?

Возвращаемое значение Y & не создает аналогичное сообщение об ошибке.

Возможно, я использую неправильный подход для достижения того, чего хочу, - не стесняйтесь, дайте мне знать.

+1

Несвязанный: вы возвращаете ссылку на локальную переменную, следовательно * ссылку на обман * – vsoftco

+0

Это правда. Я просто хотел, чтобы образец был скомпилирован. – User

ответ

2

Почему параметр не является ссылкой на объект Y, когда Y реализует X?

Потому что вы должны дать точную подпись, как было объявлено в чистой виртуальной функции базы.

Вот почему

class Y : public X<int> { 
    // ... 
    X<int>& doStuff(X<int>& x) override; 
}; 

работы.

См. Рабочий Live Demo.


Не говоря уже о том, что возвращает ссылку на локальную переменную не определено поведение.

+0

Да здравствует ключевое слово 'override' :) – vsoftco

+0

@vsoftco Да! –

3

Установив Y& в качестве параметра, вы можете изменить подпись doStuff и поэтому res является абстрактным.

X<int>& не Y&, хотя Y наследует X.

+0

Но он, похоже, работает для возвращаемого значения. – User

+3

@User Это из-за [* ковариантных типов возврата *] (http: //www.lwithers.me.uk/articles/covariant.html). Виртуальной функции разрешено возвращать указатель или ссылку на производную, все еще считающуюся переопределением. – vsoftco

+0

Хорошо - имеет смысл. Но как я должен реализовать то, что я хочу? Просто используйте X вместо Y и все? – User