-
类模板和函数模板一样,使用关键字
template
引入一个类模板。类模板是创建类的模式,通过提供模板参数来实现,例如Point<int>
。 -
类模板的成员函数本身就是函数模板,使用相同的模板参数,只是将模板参数提供给类,而不是函数,就像在下面示例中函数
Point<T>::moveTo
实现的那样。 -
每当使用不同的模板参数时,编译器就会生成一个新的类实例,具有新的成员函数。
也就是说,Point<int>::moveTo
是一个函数,Point<double>::moveTo
是另一个函数,这正是手动编写这些函数会发生的情况。如果两个不同的源文件都使用Point<int>
,编译器和链接器会确保它们共享同一个模板实例。 -
也正因为如此不能把一个
Point<int>
对象赋给一个Point<float>
对象,详见下面代码中注释掉的pt3 = pt2
后面的报错信息。 -
下面代码也给出了类内又有模板的实现方式。
#include <iostream>
#include <vector>template<class T>
class Point{
public:Point(T x, T y):x_(x), y_(y){std::cout << __PRETTY_FUNCTION__ << std::endl;}Point(const Point& pt): x_(pt.x_), y_(pt.y_){std::cout << __PRETTY_FUNCTION__ << std::endl;}Point& operator=(const Point& pt)& {Point(pt.x_, pt.y_).swap(static_cast<Point&>(*this));std::cout << __PRETTY_FUNCTION__ << std::endl;return *this;}Point(Point&& pt) noexcept: x_(pt.x_), y_(pt.y_) {std::cout << __PRETTY_FUNCTION__ << std::endl;}Point& operator=(Point&& pt)& noexcept{x_ = pt.x_;y_ = pt.y_;std::cout << __PRETTY_FUNCTION__ << std::endl;return *this;}void swap(Point& pt) noexcept{std::swap(x_, pt.x_);std::swap(y_, pt.y_);std::cout << __PRETTY_FUNCTION__ << std::endl;}virtual ~Point(){std::cout << __PRETTY_FUNCTION__ << std::endl;}T getX()const{return x_;}T getY()const{return y_;}void moveTo(T x, T y);/*【类内又有模板】方式一,在类内声明,在类外定义 */template<class U>U ratio() ;/*【类内又有模板】方式二,在类内定义 */template<class V>V multiply() {return static_cast<V>(x_) * static_cast<V>(y_);}private:T x_;T y_;
};template<class T>
void Point<T>::moveTo(T x, T y){x_ = x;y_ = y;
}template<class T>
template<class U>
U Point<T>::ratio() {return static_cast<U>(x_) / static_cast<U>(y_); // omit devided by zero.
}int main() {Point<int> pt1(1, 2);Point<float> pt2(3.4, 5.6);Point<int> pt3(pt1);pt3 = pt1;//pt3 = pt2; // error: no match for 'operator=' (operand types are 'Point<int>' and 'Point<float>')std::cout << "x = "<< pt3.getX() << ", y = " << pt3.getY() << std::endl; // x = 1, y = 2】pt3.moveTo(5, 6);std::cout << "x = "<< pt3.getX() << ", y = " << pt3.getY() << std::endl; // x = 5, y = 6std::cout << pt3.ratio<float>() << std::endl; // 0.833333std::cout << pt3.multiply<float>() << std::endl; // 30
}