2016-09-01 2 views
-3

Я работаю над небольшим проектом, чтобы понять, как работают шаблоны C++. В принципе, у меня есть что-то вроде:C++ class template as function return type

class Base{ 
public: 
    MyOperation<Base> operate(Base x){ return MyOperation<Base>(x); } //error here 
}; 

//... 

template<class B> 
class MyOperation : public Base{ 
public: 
    B b; 
    MyOperation(B b_){ b = b_; } 
}; 

При попытке компиляции моей программы, я получаю сообщение об ошибке (Error C2143, отсутствующий ';' до '<'). Это потому, что я не могу использовать MyOperation в качестве возвращаемого типа функции funcion()?

Заранее спасибо.

+4

Является ли этот 'template (класс B)' правильным синтаксисом? – nbro

+0

Компилятор должен показать вам строку. Обычно, если ошибка упоминает синтаксис, вы испортили синтаксис. Здесь у вас есть шаблон (класс B) ', когда он должен быть' template '. Может быть, это ваш псевдокод, иначе я бы опубликовал этот ответ. – TankorSmash

+1

'Base' не может _see_' MyOperation', потому что он определен _after_ 'Base'. –

ответ

3

Синтаксис объявления шаблона: template<class B> (или, что эквивалентно, template<typename B>).

Также имеется круговая ссылка: Base ссылки MyOperation (тип возврата и внутри функции operate). Таким образом, MyOperation необходимо будет определить до Base.

Но MyOperation также ссылки Base (базовый класс).

Для базового класса и для использования внутри функции требуется полное определение. Но для возвращаемого типа достаточно неполного типа. Так MyOperation необходимо будет предопределенные до того Base, как:

template<class B> class MyOperation; 

И кроме того, operate() должен быть определен (не декларируется) за пределами class Base { ... }, после определения MyOperation. Правильный код будет выглядеть так:

// pre-declaration of MyOperation 
template<class B> class MyOperation; 

// definition of Base class 
class Base { 
public: 
    // declaration of Base::operate member function 
    // MyOperation<Base> is incomplete type here 
    MyOperation<Base> operate(Base x); 
}; 

// definition of MyOperation class template 
template<class B> 
class MyOperation : public Base{ 
public: 
    B b; 
    MyOperation(B b_){ b = b_; } 
}; 

// definition ofBase::operate member function 
inline MyOperation<Base> Base::operate(Base x) { 
    return MyOperation<Base>(x); 
} 

Base::operate должен быть рядным, если определение находится в заголовочном файле, в противном случае будет несколько символами линкера, если заголовок включен несколько исходных файлами.

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

+0

Спасибо, я новичок в программировании, поэтому я не думал о круговых ссылках. – user2440822