扩展补充:static、类模板、函数模板
一、static
静态成员:只存在一份。
静态成员的用处:有100个人去银行存钱,那100个的账号都是不同的,但是他们都有相同的利率,利率就用静态成员存储。
静态成员函数:只存在一份,与普通成员函数的区别:不含this指针。
特点:只能处理静态成员/数据。
class Account{
public:
static double m_rate;
static void set_rate(const double& x){ m_rate = x; }
};
//注意:一定要在类外对static变量进行如下定义,可以不用赋值
double Account::m_rate = 8.0; //可写成 double Account::m_rate
int main(){
// 静态成员函数的调用
//1.通过类名调用
Account::set_rate(5.0); //银行没有客户时,也可以用类名调用设置利率
//2.通过对象调用
Account a;
a.set_rate(6.0);
}
class A{
public:
//通过静态函数,获取唯一的静态对象
static A& getInstance(){ return a; }
void setup(){...}
private:
//构造函数私有化,外部无法通过构造函数创建对象
A();
A(const A& rhs);
//静态对象-唯一
static A a;
};
int main(){
//通过类名调用静态成员函数(获取静态对象),进而调用非静态成员函数
A::getInstance().setup();
}
上图代码将构造函数放在private中,然后创建了一个静态对象,最后使用静态函数去调用该对象。
优点:使用者不能在创建其他A类型的对象,只能用函数调用唯一的静态对象。
缺点:若不调用静态函数,便已经创建了静态对象。
class A{
public:
//通过静态函数,获取唯一的静态对象
static A& getInstance(){
//仅当静态函数调用时,才创建唯一的静态对象
//当函数作用域结束时,唯一的静态对象仍存在
static A a;
return a;
}
void setup(){...}
private:
//构造函数私有化,外部无法通过构造函数创建对象
A();
A(const A& rhs);
};
int main(){
//通过类名调用静态成员函数(获取静态对象),进而调用非静态成员函数
A::getInstance().setup();
}
改进:在静态函数中去创建静态对象,不调用函数不会创建静态对象。
二、 模板(class template)
(1)类模板
template<typename T> //类模板
class complex{
private:
T re, im; //模板
friend complex& __doap1 (complex *ths, const complex& r); //友元函数
public:
complex(T r = 0, T i = 0) : re(r), im(i){} //默认参数、初始化列表
complex& operate+=(const complex&); //重载运算符
T real() const { return re; } //成员函数-常函数
T imag() const { return im; }
};
(2)函数模板(function template)
//函数模板
template<class T>
inline const T& min(const T& a, const T& b){
return b < a ? b : a;
}
class stone{
public:
stone(int w, int h, int we) : _w(w), _h(h), _weight(we){}
//重载运算符<
bool operator< (const stone& rhs){
return this->_weight < rhs._weight;
}
private:
int _w, _h, _weight;
}
int main(){
stone r1(2, 3), r2(3, 3), r3;
//调用模板函数min,类型推导
//类型推导T为stone类型,进一步调用stone::operator<
r3 = min(r1, r2);
}
差别:函数模板具有引用推导功能,故在使用函数时不需要用<>表明T到底是哪种类型。而类模板在创建对象时必须在类名后用<>表明T的类型。
命名空间(namespace)
using directive
using编译指令:使用指定命名空间。使用using编译指令后,可直接访问命名空间的成员,而无需使用作用域运算符 。
#include <iostream>
using namespace std;
int main(){
cin >> ... ;
cout << ... ;
return 0;
}
using declaration
using声明:使用指定命名空间的成员。使用using声明后,可直接访问命名空间的成员,而无需使用::作用域运算符。
#include <iostream>
using std::cout;
int main(){
std::cin >> ... ;
cout << ... ;
return 0;
}