模板篇
友元函数
关键字:friend
友元全局函数
友元成员函数
class Coordinate
{
friend void printXY(Coordinate &c);
};
友元,可以访问对象中的 private
和protected
数据成员
虽然方便数据的直接访问,但是也破坏了封装性。不建议使用友元
友元类
class Circle;
class Coordinate{
friend Circle;
};
Circle 对象就可以任意访问 Coordinate 对象的 数据成员 和 成员函数
关于友元的注意事项
- 友元关系不可传递
- 友元关系的单向性
- 友元声明的形式及数量不受限制
友元只是封装的补充,不建议
注:由于编译器不同,友元类有两种写法。1、friend class 类名; 2、friend 类名;
static
静态数据成员
静态成员函数
静态数据成员一般不在构造函数中实例化,一般单独进行
class Tank{
public:
Tank() {s_iCount++;}
~Tank() {s_iCount--;}
static int s_iCount;
static int getCount();
};
int Tank::s_iCount = 0;
静态数据和函数的访问:(共享)
int main(void)
{
cout << Tank::getCount() << endl;
cout << Tank::s_iCount << endl;
Tank tank;
cout << tank.getCount() << endl;
cout << tank.s_iCount << endl;
return 0;
}
从this 指针谈静态成员函数
class Tank
{
public:
void fire();
static int getCount();
private:
string m_strCode;
static int s_iCount;
}
// 实际上,fire函数会隐式传入一个 this 指针
void fire(Tank *this) {
this->m_strCode = "01";
s_iCount = 0;
}
// 静态成员函数则不会 隐式 传入一个 this 指针
static int getCount() {
m_strCode = "01"; // 报错
return s_iCount;
}
注意事项
- 静态数据成员必须单独初始化
- 静态成员函数不能调用非静态成员函数和非静态数据成员
- 静态数据成员只有一份,且不依赖对象而存在,sizeof 不计算
- 静态成员函数无法加 const,这与 this 指针的本质是相符合的
运算符重载
给原有的运算符赋予新的功能
如:给 + 号重载,使其能够实现两个字符串拼接
运算符重载的本质:函数重载
关键字:operator
一元运算符重载
-(负号)的重载:
-
友元函数重载
class Coordinate{ friend Coordinate& operator-(Coordinate &coor); }; // 定义 Coordinate& operator-(Coordinate &coor) { coor.m_iX = -coor.m_iX; coor.m_iY = -coor.m_iY; return *this; } // 使用 Coordinate coor1(3,5); -coor1; // operator-(coor1);
-
成员函数重载
class Coordinate{ public: Coordinate& operator-(); }; // 定义 Coordinate& Coordinate::operator-() { m_iX = -m_iX; m_iY = -m_iY; return *this; } // 使用 Coordinate coor1(3,5); -coor1; // coor1.operator-();
++符号的重载:
-
前置++符号重载
class Coordinate{ Coordinate& operator++(); // 前置++ }; // 定义 Coordinate& Coordinate::operator++(){ m_iX++; m_iY++; return *this; } // 使用 Coordinate coor1(3,5); ++coor1; // coor1.operator++();
-
后置++符号重载
Coordinate operator++(int); // 后置++ // 定义 Coordinate operator++(int){ Coordinate old(*this); m_iX++; m_iY++; return old; } // 使用 coor1++; // coor1.operator++(0);
二元运算符重载
+号运算符:
-
成员函数重载:
class Coordinate{ public: Coordinate operator+(const Coordinate &coor); }; // 定义 Coordinate operator+(const Coordinate &coor) { Coordinate temp; temp.m_iX = this->m_iX + coor.m_iX; temp.m_iY = this->m_iY + coor.m_iY; return temp; } // 使用 Coordinate coor1(3,5); Coordinate coor2(4,7); coor3 = coor1 + coor2; // coor1.operator+(coor2);
-
友元函数重载:
class Coordinate{ friend Coordinate operator+(const Coordinate &c1,const Coordinate &c2); }; // 定义 Coordinate operator+(const Coordinate &c1,const Coordinate &c2){ Coordinate temp; temp.m_iX = c1.m_iX + c2.m_iX; temp.m_iY = c1.m_iY + c2.m_iY; return temp; } // 使用 coor3 = coor1 + coor2; // operator+(coor1,coor2);
<< 运算符:
-
友元函数重载:
class Coordinate{ friend ostream& operator<<(ostream &out,const Coordinate &coor); }; // 定义 ostream &operator<<(ostream &out, const Coordinate &coor){ out << coor.m_iX << "," << coor.m_iY; return out; } // 使用 cout << coor; // operator<<(cout,coor);
-
**成员函数重载:**和this 的本质有关, << 运算符必须传入 ostream,所以不能重载
[] 运算符
-
成员函数
class Coordinate{ public: int operator[](int index); }; // 定义 int Coordinate::operator [](int index) { if(index == 0) { return m_iX; } if(index == 1) { return m_iY; } } // 使用 Coordinate coor(3,5); cout << coor[0]; // coor.operator[](0); cout << coor[1]; // coor.operator[](1);
-
**友元函数重载:**和 this 本质有关, [] 运算符必须传入 索引 值,所以不能重载
函数模板
关键字: template typename class
template <class T>
T max(T a,T b) {
return (a > b) ? a : b;
}
// 使用
int ival = max(100,99);
char cval = max<char>('A','B');
template<typename T>
void swap(T &a,T &b) {
T tmp = a;
a = b;
b = tmp;
}
// 使用
int x = 20,y = 30;
swap<int>(x,y);
**注意:**如果只有函数模板 而没有对其进行调用,编译后是不会产生代码逻辑的,因为类型不确定,并不知道产生什么具体类型的函数
变量作为模板参数
template<int size>
void display()
{
cout << size << endl;
}
display<10>();
多参数函数模板
template <typename T,typename C>
void display(T a,C b) {
cout << a << " " << b << endl;
}
// 使用
int a = 1024;
string str = "Hello world!";
display<int,string>(a,str);
typename 和 class 意义一样,可以混用
函数模板与重载
template<typename T>
void display(T a);
template<typename T>
void display(T a,T b);
template<typename T,int size>
void display(T a);
类模板
template<class T>
class MyArray{
T *m_pArr;
};
template<class T>
void MyArray<T>::display(){
...
}
// 使用
MyArray<int> arr;
arr.display();
注意:模板代码不能分离编译
C++标准模板 STL
STL:Standard Template Lib
vector 向量
本质:对数组的封装
动态增加或者减小数组长度
特点:读取能在常数时间完成
vector 初始化:
vector<int> ivec1;
vector<int> ivec2(ivec1);
vector<string> svec1;
vector<string> svec2(ivec);
vector<int> ivec4(10,-1);
vector<string> svec(10, "hi!");
vector 常用函数:
vector 使用:
vector<int> vec;
vec.push_back(10);
vec.pop_back();
cout << vec.size() << endl;
for(int k = 0;k < vec.size();k++) {
cout << vec[k] << endl;
}
迭代器:iterator
vector vec;
vec.push_back("hello");
vector<string>::iterator citer = vec.begin();
for(;citer != vec.end();citer++) {
cout << *citer << endl;
}
list:链表
特点:数据插入速度快
map:映射
map<int,string> m;
pair<int,string> p1(10,"shanghai");
pair<int,string> p2(20,"beijing");
m.insert(p1);
m.insert(p2);
cout << m[10] << endl;
cout << m[20] << endl;
pair<int,string> p1("S","shanghai");
pair<int,string> p2("B","beijing");
m.insert(p1);
m.insert(p2);
cout << m["S"] << endl;
cout << m["B"] << endl;