C++学习笔记

Catalogue   

函数重载(Function Overloading)

定义:函数名相同,函数的参数列表包括参数的类型、参数的个数和参数的顺序,只要有一个不同就叫做参数列表不同。

1
2
3
4
5
// 解析XML字符串的函数族,支持int、char *和double三种类型。
// 返回值:0-成功,-1-失败。
int GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,int *out_Value);
int GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,char *out_Value);
int GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,double *out_Value);

C++编译器在编译的时候会根据参数列表的类型对函数进行重命名,比如:

1
int GetXMLBuffer_char_char_int(const char *in_XMLBuffer,const char *in_FieldName,int *out_Value);

结构体新特征

在C++中,结构体的成员可以有函数。

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

#include <stdio.h>
#include <string.h>

struct st_girl {
char name[50]; // 姓名
int age; // 年龄
int height; // 身高,单位:厘米cm
char sc[30]; // 身材,火辣;普通;飞机场。
char yz[30]; // 颜值,漂亮;一般;歪瓜裂枣。
int show(); // 声明结构体成员函数show,用于显示其它成员变量的值。
};

int main() {
st_girl stgirl; // struct关键定可以不书写
memset(&stgirl, 0, sizeof(stgirl));
strcpy(stgirl.name, "西施");
stgirl.age = 22;
stgirl.height = 168;
strcpy(stgirl.sc, "火辣");
strcpy(stgirl.yz, "漂亮");

stgirl.show(); // 调用结构体的成员函数
}

int st_girl::show() // 结构体st_girl成员函数的定义
{
printf("name=%s,age=%d,height=%d,sc=%s,yz=%s\n", name, age, height, sc, yz);
}

类详解

构造函数

  1. 构造函数必须是 public 属性。
  2. 构造函数没有返回值,因为没有变量来接收返回值,即使有也毫无用处,不管是声明还是定义,函数名前面都不能出现返回值类型,即使是 void 也不允许。
  3. 构造函数可以有参数,允许重载。一个类可以有多个重载的构造函数,创建对象时根据传递的参数来判断调用哪一个构造函数。
  4. 构造函数在实际开发中会大量使用,它往往用来做一些初始化工作,对成员变量进行初始化等,注意,不能用memset对整个类进行初始化。

析构函数

  1. 析构函数必须是 public 属性的。
  2. 析构函数没有参数。
  3. 析构函数没有返回值,因为没有变量来接收返回值,即使有也毫无用处,不管是声明还是定义,函数名前面都不能出现返回值类型,即使是 void 也不允许。
  4. 析构函数不允许重载的。一个类只能有一个析构函数。
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
//头文件

class CFile
{
private:
FILE *m_fp; // 文件指针
bool m_bEnBuffer; // 是否启用缓冲区,true-启用;false-不启用

public:
CFile(); // 类的构造函数
CFile(bool bEnBuffer); // 类的构造函数

~CFile(); // 类的析构函数

void EnBuffer(bool bEnBuffer=true); // 启、禁用缓冲区

// 打开文件,参数与fopen相同,打开成功true,失败返回false
bool Open(const char *filename,const char *openmode);

// 调用fprintf向文件写入数据
void Fprintf(const char *fmt, ... );

// 调用fgets从文件中读取一行
bool Fgets(char *strBuffer,const int ReadSize);

// 关闭文件指针
void Close();
};




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//实现文件

CFile::CFile() // 类的构造函数
{
m_fp=0;
m_bEnBuffer=true;
}

CFile::CFile(bool bEnBuffer) // 类的构造函数
{
m_fp=0;
m_bEnBuffer=bEnBuffer;
}

CFile::~CFile() // 类的析构函数
{
Close(); // 调用Close释放资源
}

C++引用

引用就是变量的别名,对引用的操作与对变量直接操作完全一样。

1
2
3
4
5
//数据类型 &引用名=目标变量名;
int ii;
int &rii=ii; // 定义引用rii,它是变量ii的引用,即别名。
rii=1; 等价于 ii=1;

  1. &在此不是求地址运算,而是声明引用。
  2. 数据类型可以是C语言的基本数据类型,也可以是结构体和类等构造类型。
  3. 引用在声明的时候必须对其进行初始化(指向目标变量名),否则编译器会报错。
  4. 引用初始化之后,不能再用作其他变量名的别名。
  5. 引用声明后,相当于目标变量名有两个名称。
  6. 不能建立数组的引用,因为数组是多个变量的集合。
  7. 引用可以用const修饰,表示只读,用这种方式声明的引用,不能通过引用名对目标变量的值进行修改。

运算符重载

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
#include <stdio.h>
#include <string.h>

class CGirl // 定义类
{
public:
char m_name[50]; // 姓名
char m_sc[30]; // 身材,火辣;普通;飞机场。

bool operator==(const CGirl &Girl); // 重载==运算符
};

int main()
{
CGirl Girl1,Girl2;

strcpy(Girl1.m_name,"西施");
strcpy(Girl2.m_name,"东施");

if (Girl1 == Girl2) printf("Girl1和Girl2是同一个人。\n");
else printf("Girl1和Girl2不是同一个人。\n");
}

bool CGirl::operator==(const CGirl &Girl) // 重载==运算符
{
// 如果两个类的姓名相同,就相等
if (strcmp(m_name,Girl.m_name)== 0) return true;

return false;
}

string类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <string>
//string是一个模板类,位于std命名空间内,为方便使用还需要在程序中增加:
using namespace std; // 指定缺省的使名空间。
string str; // 创建string对象。

//如果不指定命名空间
std::string str;

const char *c_str();//c_str函数返回这个字符串的地址

int size(); // 返回当前字符串的大小。
int length(); // 返回当前字符串的长度,注意和size的区别。
void clear(); // 清空字符串。


vector类

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
iterator begin():返回容器头的指针,指向容器第一个元素的位置。

iterator end():返回容器尾的指针,指向容器最后一个元素的下一个位置。

void push_back(const T& x):向容器的尾部增加一个元素x。

iterator insert(iterator it,const T& x):向容器中指定位置(it)前插入一个元素x。

iterator erase(iterator it):删除容器中指定位置(it)的元素。

bool empty():判断容器是否为空。

int size():返回容器中元素的个数。

sort(begin,end,cmp);

/**
sort函数包含在头文件为#include <algorithm>的c++标准库中,调用排序方法不必知道其内部是如何实现的,只要出现我们想要的结果就行。

sort函数有三个参数:

(1)第一个是要排序的数组的起始地址。

(2)第二个是结束的地址。

(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时缺省的排序方法是从小到大排序。如果vector容器中元素的数据类型不是基本数据类型,sort函数必须指定排序方法函数。
**/

C++动态内存

1
2
3
4
5
6
7
8
9
10
11
12
datatype *pointer = new datatype;
// 其它代码
delete pointer;
//datatype可以是C语言的基本数据类型,也可以是结构体,还可以是类。
//pointer是一个指针,指向new返回的地址。

int *pi= new int; // 动态分配一个整数大小的内存
(*pi)=10;
delete pi; // 释放pi指向的内存



继承和派生

1
2
3
4
5
6
7
8
9
10
11
12
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
// 派生类类体
};

class CGirl // 定义超女类
{
}

class CKCon:public CGirl // 定义王妃类,从超女类继承
{}

当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种方式,当使用不同类型的继承时,遵循以下几个规则:

  1. 公有继承(public):当类派生以public方式继承时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
  2. 保护继承(protected): 当类派生以protected方式继承时,基类的公有和保护成员将成为派生类的保护成员。
  3. 私有继承(private):当类派生以private方式继承时,基类的公有和保护成员将成为派生类的私有成员。

多态

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

#include <stdio.h>
#include <string.h>

class CGirl // 定义超女类
{
public:
char m_name[50]; // 姓名
int m_age; // 年龄
int m_height; // 身高,单位:厘米cm
char m_sc[30]; // 身材,火辣;普通;飞机场。
char m_yz[30]; // 颜值,漂亮;一般;歪瓜裂枣。

int Show() // 显示超女基本信息的成员函数体
{ printf("CGirl 姓名:%s,年龄:%d,身高:%d,身材:%s,颜值:%s\n", m_name, m_age, m_height, m_sc, m_yz); }
};

class CKCon : public CGirl // 定义王妃类,从超女类继承
{
public:
char m_ch[50]; // 称号
char m_palace[50]; // 居住的宫殿
int m_sal; // 奉禄

int Show() // 显示王妃的称号、宫殿和奉禄
{ printf("CKCon 姓名:%s,称号:%s,栖:%s,奉禄:%d两银子。\n", m_name, m_ch, m_palace, m_sal); }
};

int main() {
CKCon KCon;

strcpy(KCon.m_name, "杨玉环");
KCon.m_age = 28;
KCon.m_height = 168;
strcpy(KCon.m_sc, "火辣");
strcpy(KCon.m_yz, "漂亮");
strcpy(KCon.m_ch, "杨贵妃");
strcpy(KCon.m_palace, "华清宫");
KCon.m_sal = 10000;

CGirl *pGirl; // 基类的指针
CKCon *pCon; // 派生类的指针

pGirl = pCon = &KCon; // 都指向派生类

pGirl->Show(); // 将调用的是基类的Show方法
pCon->Show(); // 将调用的是派生类的Show方法
}

动态多态

动态多态是在程序运行时根据基类的引用(指针)指向的对象来确定自己具体该调用哪一个类的虚函数。在CGirl类中,Show方法的声明前放置关键字 virtual,则pGirl->Show()会打印出CKCon中的show方法内容。

虚函数

虚函数是在基类中使用关键字 virtual 声明的函数,在派生类中重新定义虚函数。我们想要的是在程序中可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。

纯虚函数

只声明,具体实现在派生类中实现

1
2
3
4
5
6
7
8
9
10
11
class CGirl    // 定义超女类
{
public:
char m_name[50]; // 姓名
int m_age; // 年龄
int m_height; // 身高,单位:厘米cm
char m_sc[30]; // 身材,火辣;普通;飞机场。
char m_yz[30]; // 颜值,漂亮;一般;歪瓜裂枣。

virtual int Show()=0; // 申明一个纯虚函数。
};