Fork me on GitHub

C++-模板篇


友元函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Coordinate
{
friend void printXY(Coordinate &c);
public:
Coordinate(int x,int y);
private:
int m_iX;
int m_iY;
};

void printXY(Coordinate &c)
{
cout<<c.m_iX<<c.m_iY; // 声明为Coordinate类的友元函数后,该函数可以直接访问该类的私有成员
}

int main()
{
Coordinate coor(3,5);
printXY(coor); // 传入对象名而非地址
return 0;
}

友元函数中的参数必须要是该类本身或者引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Coordinate
{
friend void Circle::printXY(Coordinate &c);
public:
Coordinate(int x,int y);
private:
int m_iX;
int m_iY;
};

class Circle
{
public:
void printXY(Coordinate &c)
{
cout<<c.m_iX<<c.m_iY;
}
};

int main()
{
Coordinate coor(3,5);
Circle circle;
circle.printXY(coor);
return 0;
}

友元类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Circle; // 注意
class Coordinate
{
friend Circle; // 注意
public:
Coordinate(int x,int y);
private:
int m_iX;
int m_iY;
};

class Circle
{
public:
void printXY
{
cout<<m_coor.m_iX<<m_coor.m_iY;
}
private:
Coordinate m_coor;
};

关于友元的注意事项

  • 友元关系不能传递
  • 友元关系的单向性
  • 友元声明的形式及数量不受限制

友元只是封装的补充,破坏了封装性,如果在早期很好的设计类,可以避免使用友元

static

静态数据成员

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Tank
{
public:
Tank(){s_iCount++;}
~Tank(){s_iCount--;}
static int getCount(){return s_iCount;}
static int s_iCount;
private:
string m_strCode;
};
int Tank::s_iCount = 0;

int main()
{
cout<<Tank::getCount()<<endl;
cout<<Tank::s_iCount<<endl;
Tank tank;
cout<<tank.getCount()<<endl;
cout<<tank.s_iCount<<endl;
}
  1. 静态数据成员不依赖于对象而是依赖与类
  2. 静态成员函数只能调用静态数据成员和静态成员函数
  3. 静态数据成员必须单独初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
class Tank
{
public:
static int getCount()
{
m_strCode = "01"; // 错误
return s_iCount;
}
private:
string m_strCount;
static int s_iCount;
};
int Tank::s_iCount = 0;

一元运算符重载

-(负号)的重载可以分为友元函数重载和成员函数重载

成员函数重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Coordinate
{
public:
Coordinate(int x,int y);
Coordinate& operator-();

private:
int m_iX;
int m_iY;
};

Coordinate& Coordinate::operator-()
{
m_iX = -m_iX;
m_IY = -m_iY;
return *this;
}

int main()
{
Coordinate coor1(3,5);

-coor1; // coor1.operator-();

return 0;
}

友元函数重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Coordinate
{
friend Coordinate& operator-(Coordinate &coor);
public:
Coordinate(int x,int y);
private:
int m_iX;
int m_iY;
};

Coordinate& operator-(Coordinate &coor)
{
coor.m_iX = -coor.m_iX;
coor.m_iy = -coor.m_iY;

return *this;
}

int main()
{
Coordinate coor1(3,5);

-coor1; // operator-(coor1);

return 0;
}

前置++符号重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Coordinate
{
public:
Coordinate(int x,int y);
Coordinate& operator++(); // 前置++
private:
int m_iX;
int m_iY;
};

Coordinate& Coordinate::operator++()
{
m_iX++;
m_iY++;

return *this;
}

int main()
{
Coordinate coor1(3,5);
++coor1; // coor1.operator++();

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Coordinate
{
friend Coordinate& operator++(Coordinate &c);
public:
Coordinate(int x,int y);
private:
int m_iX;
int m_iY;
};

Coordinate& operator++(Coordinate &coor)
{
coor.m_iX++;
coor.m_iY++;
return *this;
}

int main()
{
Coordinate coor1(3,5);
++coor1; // operator++(coor1);

return 0;
}

后置++重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Coordinate
{
public:
Coordinate(int x,int y);
Coordinate operator++(int); // 后置++,返回值没有用&引用,与前置++的区别,并且一定要传入int
private:
int m_iX;
int m_iY;
};

Coordinate Coordinate::operator++(int)
{
Coordinate old(*this);
m_iX++;
m_iY++;
return old;
}

int main(void)
{
Coordinate coor1(3,5);
coor1++; //coor1.operator++(0);

return 0;
}

二元运算符重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Coordinate
{
public:
Coordinate(int x,int y);
Coordinate operator+(const Coordinate &coor);

private:
int m_iX;
int m_iY;
};

Coordinate 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;
}

int main()
{
Coordinate coor1(3,5);
Coordinate coor2(4,7);
Coordinate coor3(0,0);
coor3 = Coor1 + coor2; //coor1.operator+(coor2);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Coordinate
{
friend Coordinate operator+(const Coordinate& c1,const Coordinate &c2);
public:
Coordinate(int x,int y);
private:
int m_iX,m_iY;
};

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;
}

int main(void)
{
Coordinate coor1(3,5);
Coordinate coor2(4,7);
Coordinate coor3(0,0);
coor3 = Coor1 + coor2; //operator+(coor1,coor2);
return 0;
}

输出运算符重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Coordinate
{
friend ostream& operator<<(ostream &out,const Coordinate &coor);
public:
Coordinate(int x,int y);
private:
int m_iX;
int m_iY;
};

ostream& operator<<(ostream &out,const Coordinate &coor)
{
out<<coor.m_iX<<","<<coor.m_iY;

return out;
}

int main(void)
{

Coordinate coor(3,5);
cout<<coor; // operator<<(cout,coor);
}

返回必须是ostream&,所传入的第一个参数必须是ostream &
输出运算符不能用成员函数重载,因为他的第一个参数必须是ostream&,而成员函数重载的第一个参数默认是该类对象的引用

[]运算符重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Coordinate
{
public:
Coordinate(int x,int y);
int operator[](int index);
private:
int m_iX;
int m_iY;
};

int Coordinate::operator[](int index)
{
if(0 == index)
{return m_iX;}
if(1 == index)
{return m_iY;}
}

int main(void)
{
Coordinate coor(3,5);
cout<<coor[0]; //coor.operator[](0);
cout<<coor[1]; //coor.operator[](1);

return 0;
}

索引运算符不能用友元函数重载,因为友元函数的第一个参数可以是类的this指针,也可以是其他的,但索引运算符[]的第一个参数必须是this指针

函数模板

1
2
3
4
5
template <Class T>
T max(T a, T b)
{
return (a > b)?a:b;
}
1
2
3
4
5
6
7
8
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);

函数模板与重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);

display<int>(10)

display<int>(10,10)

display<int,5>(30)

类模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template<class T>
class MyArray
{
public:
void display()
{}
private:
T *m_pArr;
};

template<class T>
void MyArray<T>::display()
{
// to do
}

int main(void)
{
MyArray<int> arr;
arr.display();

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template <typename T,int KSize>
class Container
{
public:
void display();
private:
T m_obj;
};

template<typename T,int KSize>
void Container<T,KSize>::display()
{
for(int i = 0; i < KSize; i++)
{
cout<<m_obj<<endl;
}
}

int main(void)
{
Container<int,10> ct1;
ct1.display();

return 0;
}

**模板代码不能分离编译,也就是说不能分别写成.h.cpp文件

标准模板类STL

vector

特点:读取能在常数时间完成

初始化vector对象的方式
vector v1 vector保存类型为T的对象。默认构造函数v1为空
vector v2(v1) v2是v1的一个副本
vector v3(n,i) v3包含n个值为i的元素
vector v4(n) v4包含有值初始化元素的n个副本
vector常用函数
empty() 判断向量是否为空
begin() 返回向量迭代器首元素
end() 返回向量迭代器末元素的下一个元素
clear() 清空向量
front() 第一个数据
back() 最后一个数据
size() 获得向量中数据大小
push_back(elem) 将数据插入向量尾
pop_back() 删除向量尾部数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main(void)
{
vector<int> vec;
vec.push_back(10);
vec.pop_back();
cout<<vec.size()<<endl;

return 0;
}

for(int k = 0 ; k < vec.size(); k++)
{
cout<<vec[k]<<endl;
}

迭代器

1
2
3
4
5
6
7
8
9
10
int main()
{
vector vec;
vec.push_back("hello");
vector<string>::iterator citer = vec.begin();
for(;citer != vec.end();citer++)
{ cout<<*citer<<endl; }

return 0;
}

链表list

映射map

1
2
3
4
5
6
7
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;

代码实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include<iostream>
#include<stdlib.h>
#include<vector>
#include<list>
#include<map>
#include<string>
using namespace std;

int main()
{
vector<int> vec;
vec.push_back(3);
vec.push_back(4);
vec.push_back(6);
// vec.pop_back();
//cout<<vec.size()<<endl;
/*for(int i = 0 ; i < vec.size(); i++)
{
cout<<vec[i]<<endl;
}*/

vector<int>::iterator itor = vec.begin();
cout<<*itor<<endl;
for(;itor != vec.end(); itor++)
{
itor++;
}
cout<<vec.front()<<endl;
cout<<vec.back()<<endl;

list<int> list1;
list1.push_back(4);
list1.push_back(7);
list1.push_back(10);

/*for(int i = 0 ; i < list.size() ; i++)
{
cout<<list1[i]<<endl; // 错误
}*/

list<int>::iterator itor = list1.begin();
for(;itor != list1.end(); itor++)
{
cout<<*itor<<endl;
}

map<int,string> m;
pair<int,string> p1(3,"hello");
pair<int,string> p2(6,"world");
m.insert(p1);
m.insert(p2);
cout<<m[3]<<endl;
cout<<m[6]<<endl;

// 遍历必须用迭代器
map<int,string>::iterator itor = m.begin();
for(;itor != m.end() ; itor++)
{
// cout<<*itor<<endl; 错误
cout<<itor->first<<endl;
cout<<itor->second<<endl;
cout<<endl;
}

return 0;
}

坚持原创技术分享,您的支持将鼓励我继续创作
-------------本文结束感谢您的阅读-------------
0%