2012-12-26 192 views
0

可能重复:
Undefined symbol on a template operator overloading function问题与模板C++

这里是我的源代码。 在Number.h

#ifndef NUMBER_H 
#define NUMBER_H 

#include <iostream> 
using std::istream; 
using std::ostream; 

template <class T> class Number; 

template <class T> 
ostream& operator<<(ostream&, const Number<T>&); 

template <class T> 
istream& operator>>(istream&, Number<T>&); 

template <class T> 
class Number{ 
public: 
    Number(const T &n) :i(n) {} 
    Number()   :i(0) {} 
    T& operator+(const Number&rhs) const; 
    T& operator-(const Number&rhs) const; 
    T& operator*(const Number&rhs) const; 
    T& operator/(const Number&rhs) const; 
    friend ostream& operator<< <T> (ostream& , const Number<T>&); 
    friend istream& operator>> <T> (istream& , Number<T>&); 
private: 
    T i; 
}; 

#endif 

而且在Number.cpp

#include "Number.h" 

template<class T> 
T& Number<T>::operator+(const Number&rhs) const 
{ 
    return i+rhs.i; 
} 

template<class T> 
T& Number<T>::operator-(const Number&rhs) const 
{ 
    return i-rhs.i; 
} 

template<class T> 
T& Number<T>::operator*(const Number&rhs) const 
{ 
    return i*rhs.i; 
} 

template<class T> 
T& Number<T>::operator/(const Number&rhs) const 
{ 
    return i/rhs.i; 
} 

template<class T> 
ostream& operator<<(ostream&os , const Number<T>&rhs) 
{ 
    return os<< rhs.i; 
} 

template<class T> 
istream& operator>>(istream&is , Number<T>&rhs) 
{ 
    return is >> rhs.i; 
} 

我无法找出原因有

undefined reference to `std::istream& operator>><double>(std::istream&,Number<double>&)' 
undefined reference to `Number<double>::operator+(Number<double> const&) const' 

错误等等等等

+1

[相同旧C++模板故事](HTTP://www.parashift。 com/C++ - faq-lite/templates.html) – sgarizvi

+0

也在一般undefined-references问题下描述:http://stackoverflow.com/a/12574417/777186 – jogojapan

回答

0

的所有成员函数的定义需要可用于任何翻译实例化模板的单元。设想一个包含Number.h的文件并尝试使用Number<int>。然后编译器需要生成Number的所有代码,其实例化为Tint。如果只看到Number.h,它怎么能这样做?它不知道成员函数的定义。

解决的办法是将您的成员函数(从Number.cpp)的定义放入Number.h。另外,一些人喜欢在Number.cpp命名Number.cppNumber.tpp,取而代之的#include "Number.h",把#include "Number.tpp"底部的Number.h - 基本上颠倒列入使头部始终包括落实。

+0

非常感谢。我刚接触'template' – user1668903

+0

并且你能解释为什么'#include“Number.h”'更常见的情况是当有'template' – user1668903

+0

@ user1668903我真的不明白这个问题,我很害怕。无论何时您实例化一个模板,例如'Number ',编译器都需要能够生成'Number'类,并将所有出现的'T'替换为'int'。要做到这一点,它需要能够看到Number的所有代码,所以头文件必须包含头文件和实现文件。 –

2

对于模板使用.hpp,并且不能在临时对象上返回引用。

number.h

#ifndef NUMBER_H 
#define NUMBER_H 

#include <iostream> 
using std::istream; 
using std::ostream; 

template <class T> class Number; 

template <class T> 
ostream& operator<<(ostream&, const Number<T>&); 

template <class T> 
istream& operator>>(istream&, Number<T>&); 

template <class T> 
class Number{ 
     public: 
       Number(const T &n) :i(n) {} 
       Number()   :i(0) {} 
       T operator+(const Number&rhs) const; // Error Here return T not T& 
       T operator-(const Number&rhs) const; 
       T operator*(const Number&rhs) const; 
       T operator/(const Number&rhs) const; 
       friend ostream& operator<< <T> (ostream& , const Number<T>&); 
       friend istream& operator>> <T> (istream& , Number<T>&); 
     private: 
       T i; 
}; 

#include <number.hpp> 

#endif 

number.hpp

#ifndef NUMBER_HPP 
#define NUMBER_HPP 

template<class T> 
T 
Number<T>::operator+(const Number& rhs) const 
{ 
     return i + rhs.i; 
} 

template<class T> 
T 
Number<T>::operator-(const Number&rhs) const 
{ 
     return i-rhs.i; 
} 

template<class T> 
T 
Number<T>::operator*(const Number&rhs) const 
{ 
     return i*rhs.i; 
} 

template<class T> 
T 
Number<T>::operator/(const Number&rhs) const 
{ 
     return i/rhs.i; 
} 

template<class T> 
ostream& operator<<(ostream&os , const Number<T>&rhs) 
{ 
     return os<< rhs.i; 
} 

template<class T> 
istream& operator>>(istream&is , Number<T>&rhs) 
{ 
      return is >> rhs.i; 
} 

#endif 

的main.cpp

#include <iostream> 
    #include <number.h> 

    int 
    main(int, const char**) 
    { 
     Number<double> value(1); 
     Number<double> add(3); 

     std::cout << value + add << std::endl; 
     std::cout << value * add << std::endl; 
     std::cout << value - add << std::endl; 
     std::cout << value/add << std::endl; 
     return 0; 
} 
+0

+1为完整:) – Potatoswatter