Шаблонирование класса и затем перегрузка операторов (C ++)

0

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

//In Maths.h file

template <class T> class Maths{
public:
    Maths<T>(T lhs);

    template<typename U>
    Maths<T>(const Maths<U>& otherMaths);

    ~Maths();

    template <typename U>
    Maths<T>& operator+(const Maths<U>& rhs);

    template <typename U> 
    Maths<T>& operator*(const Maths<U>& rhs);

    template <typename U> 
    Maths<T>& operator-(const Maths<U>& rhs);

private:
    T _lhs;
};



//In Maths.cpp file
#include "Maths.h"

template <class T>
Maths<T>::Maths(T lhs){
    _lhs = lhs;
    return _lhs;
}

template <class T> template <typename U>
Maths<T>::Maths(const Maths<U>& otherMaths){
    _lhs = otherMaths._lhs;
}

template <class T>
Maths<T>::~Maths(){}

template <class T> template <typename U>
Maths<T> Maths<T>::operator+(const Maths<T>& rhs){ return Maths._lhs + rhs; }

template <class T> template <typename U>
Maths<T> Maths<T>::operator-(const Maths<T>& rhs){ return Maths._lhs - rhs; }

template <class T> template <typename U>
Maths<T> Maths<T>::operator*(const Maths<T>& rhs){ return Maths._lhs * rhs; }

Проблема в VS не распознает оператор ключевого слова (т.е. Не отображается синий), почему это?

РЕДАКТИРОВАТЬ:

Я удалил приведенные ниже ошибки. Перемещено все определения в файл.h, и код все равно не будет компилироваться, ошибки найдены здесь: http://i.imgur.com/Z9rWOFh.png

новый код (если интересно):

//in Maths.h file
template <class T> class Maths{
public:
    Maths<T>(T lhs);

    template<typename U>
    Maths<T>(const Maths<U>& otherMaths);

    ~Maths();

    T& getValue(){ return _lhs; };

    template <typename U>
    Maths<T>& operator+(const Maths<U>& rhs);

    template <typename U> 
    Maths<T>& operator*(const Maths<U>& rhs);

    template <typename U> 
    Maths<T>& operator-(const Maths<U>& rhs);

private:
    T _lhs;
};

template <class T>
Maths<T>::Maths(T lhs){
    _lhs = lhs;
}

template <class T> template <typename U>
Maths<T>::Maths(const Maths<U>& otherMaths){
    _lhs = otherMaths.getValue();
}

template <class T>
Maths<T>::~Maths(){}

template <class T>
Maths<T> Maths<T>::operator+(const Maths<T>& rhs){ return _lhs + rhs.getValue(); }

template <class T> template <typename U>
Maths<T> Maths<T>::operator-(const Maths<U>& rhs){ return _lhs - rhs.getValue(); }

template <class T> template <typename U>
Maths<T> Maths<T>::operator*(const Maths<U>& rhs){ return _lhs * rhs.getValue(); }

//in main.cpp

#include "Maths.h"

int main(){
    Maths<int> x = 1;
    Maths<int> y = 5;
    x + y;
    return 0;
}
  • 0
    Вам не нужно указывать <T> после Maths для типов возвращаемых встроенных функций-членов или для имени конструктора.
  • 0
    Пожалуйста, прочтите Почему шаблоны могут быть реализованы только в заголовочном файле? Затем я рекомендую использовать g ++ или clang ++ для понятных сообщений об ошибках: coliru.stacked-crooked.com/a/9aaa7134ef8a6c28
Показать ещё 7 комментариев
Теги:
class
templates
syntax
overloading

2 ответа

1
Лучший ответ
  1. Вы не можете отделить объявление и реализацию класса шаблона в нескольких файлах. Поэтому вам нужно переместить все свои реализации в заголовок.
  2. У вас много ошибок, которые вы не видите сейчас (например, возврат в конструктор). Я рекомендую вам перемещать реализации в декларации класса. Исправьте его, отлаживайте, делайте некоторые тесты, а затем пытайтесь переместить реализации вне, если вам все еще нужно.
  3. Visual Studio (или IntelliSense в этом случае) иногда может делать некоторые ошибки при подсветке (или это может быть просто медленно). Не сосредотачивайтесь на этом. Компилятор даст вам более точные ошибки и предупреждения, если что-то не так.

Некоторые ошибки, которые я могу вам сказать:

  1. return в конструкторе Maths<T>( T lhs );
  2. return Maths._lhs + rhs; - Maths - это класс, но вы делаете операции с экземпляром. Если вам нужно взять указатель на текущий экземпляр, используйте this->_lhs _lhs или просто _lhs;
  3. _lhs = otherMaths._lhs; - вы не можете получить доступ к private полю; Вы можете получить значение _lhs класса Maths< T >, но Maths< U > - это другой класс. Поэтому вам нужно будет сделать некоторую функцию, например T& value( ) { return _lhs; } T& value( ) { return _lhs; } и использовать его здесь;

РЕДАКТИРОВАТЬ:

Есть еще некоторые ошибки. Как вы можете видеть в описании ошибки, ваша реализация

template <class T>
Maths<T> Maths<T>::operator+(const Maths<T>& rhs){ return _lhs + rhs.getValue(); }

не соответствует определению функции

// in class template <class T> class Maths
template <typename U>
Maths<T>& operator+(const Maths<U>& rhs);

(Это похоже на игру - найдите разницу = D) Правильный способ:

// declaration
template <typename U>
Maths<T> operator+(const Maths<U>& rhs);
// ...
// definition
template <class T>
template <typename U>
Maths<T> Maths<T>::operator+(const Maths<U>& rhs) { return _lhs + rhs.getValue( ); }

Я удалил объявление & из объявления и добавил template <typename U> к defenition. Для operator- и operator* вам нужно удалить &. Следующий вопрос, который вы получите, что getValue не имеет постоянной декларации. Вам нужно добавить новый метод.

const T& getValue( ) const { return _lhs; }
  • 0
    Относительно 1 .: Нет, вы можете разделить их. Для особых случаев общего программирования, например, когда вы поддерживаете только плавающие типы, это может иметь смысл. Ключевое слово здесь - «явная специализация».
  • 0
    @ phresnel прав. Другой способ - включить .cpp в файл .h после объявления класса. Я думаю, что вопрос здесь не в отделении.
Показать ещё 5 комментариев
0

Yikes... вы до сих пор не включили раннюю обратную связь. Ниже приведен компилируемый код:

template <class T>
class Maths
{
  public:
    Maths(T lhs);

    template<typename U>
    Maths(const Maths<U>& otherMaths);

    ~Maths();

    T& getValue() { return _lhs; };
    const T getValue() const { return _lhs; };

    template <typename U>
    Maths<T> operator+(const Maths<U>& rhs);

    template <typename U> 
    Maths<T> operator*(const Maths<U>& rhs);

    template <typename U> 
    Maths<T> operator-(const Maths<U>& rhs);

  private:
    T _lhs;
};

template <class T>
Maths<T>::Maths(T lhs){
    _lhs = lhs;
}

template <class T> template <typename U>
Maths<T>::Maths(const Maths<U>& otherMaths){
    _lhs = otherMaths.getValue();
}

template <class T>
Maths<T>::~Maths(){}

template <class T> template <typename U>
Maths<T> Maths<T>::operator+(const Maths<U>& rhs){ return _lhs + rhs.getValue(); }

template <class T> template <typename U>
Maths<T> Maths<T>::operator-(const Maths<U>& rhs){ return _lhs - rhs.getValue(); }

template <class T> template <typename U>
Maths<T> Maths<T>::operator*(const Maths<U>& rhs){ return _lhs * rhs.getValue(); }

//in main.cpp

#include "Maths.h"

int main()
{
    Maths<int> x = 1;
    Maths<int> y = 5;
    x + y;
}

Обратите внимание, что исправления, необходимые для компиляции, включали добавление функции const для getValue, изменение объявлений оператора для возврата Math<T> по значению, а не по ссылке.

Все, что было сказано, не имеет большого смысла сказать, что Math<int> добавленный в Math<double> возвращает Math<int>, поскольку это менее точный из двух типов. В приведенном ниже коде используется decltype для выбора того же самого типа C++, который используется при работе над двумя типами, поэтому, например, int умноженное на double возвращает double, а uint8_t (aka unsigned char), добавленный в unsigned int возвращает другую unsigned int. Я также _lhs имя переменной _lhs для n_ поскольку _lhs применим только с довольно миопической точки зрения внутри операторов... используется rhs " _lhs ", который в любом случае не имеет никакого смысла...

template <class T>
class Maths
{
  public:
    Maths(T n);

    template<typename U>
    Maths(const Maths<U>& otherMaths);

    ~Maths();

    T& getValue() { return n_; };
    const T getValue() const { return n_; };

    template <typename U>
    Maths<decltype(T()+U())> operator+(const Maths<U>& rhs);

    template <typename U> 
    Maths<decltype(T()*U())> operator*(const Maths<U>& rhs);

    template <typename U> 
    Maths<decltype(T()-U())> operator-(const Maths<U>& rhs);

private:
    T n_;
};

template <class T>
Maths<T>::Maths(T n){
    n_ = n;
}

template <class T> template <typename U>
Maths<T>::Maths(const Maths<U>& otherMaths){
    n_ = otherMaths.n_;
}

template <class T>
Maths<T>::~Maths(){}

template <class T> template <typename U>
Maths<decltype(T()+U())> Maths<T>::operator+(const Maths<U>& rhs)
{ return getValue() + rhs.getValue(); }

template <class T> template <typename U>
Maths<decltype(T()-U())> Maths<T>::operator-(const Maths<U>& rhs)
{ return getValue() - rhs.getValue(); }

template <class T> template <typename U>
Maths<decltype(T()*U())> Maths<T>::operator*(const Maths<U>& rhs)
{ return getValue() * rhs.getValue(); }

//in main.cpp

#include "Maths.h"

int main()
{
    Maths<int> x = 1;
    Maths<int> y = 5;
    x + y;
} 

Ещё вопросы

Сообщество Overcoder
Наверх
Меню