C++ note (3)
数据抽象和类 Ⅱ
C++
新增
新类型:bool
C
:
- 没有 bool 类型
1
2 - C99 定义了
_Bool
类型,并通过stdbool.h
实现与C++
兼容
C++
:
- 定义了三个关键字:
bool
,true
,false
- 当显式(例 (bool)7)或隐式(例 bool b = 7;)转为
bool
类型时0
值转为false
- 非
0
值转为true
1
2cout << true //输出 1
cout << false //输出 0
形参:void
C
:
- fn(); 没有声明形参表示函数的形参不确定
- 没有参数,则必须显式声明 fn(void);
C++
:
- fn(); 等价于 fn(void);
- 使用
…
表示可变参数1
2
3
4
5int printx(const char* fmt, ...);
// 能以一个或多个实参调用:
printx("hello world");
printx("a = %d b = %d", a, b);
新特性
函数重载
背景:
- 在开发中,需要的函数功能类似,但参数数量或类型不同
C
的解决: - 必须申明两个函数(不重名)
C++
的解决: - 声明同名函数,但参数类型不同:
1
2
3void swap(int& a, int& b);
void swap(double& a, double& b);
auto
用于函数重载
1 | void swap(int& a, int& b) { |
让编译推导决定使用哪个函数
事实上,编译器会将函数名、参数数量、参数类型编译为唯一的内部函数名
- swap_int_int
- swap_double_double
是不同的函数签名
默认实参
C
:
- 不支持函数默认参数和值
C++
:
- 默认参数只能定义在参数右边
- 一个声明和实现可匹配多个函数
fn()
fn(int)
fun(int, float)
fn(int, float, char)
1
2
3
4
5
6
7
8
9
10
11void fn(int n = 1, float b = 1.2, char c = '@'); //实现
void fn(int n, float b, char c){
cout << n << ", " << b << ", " << c << endl;
}
int main(){
fn(); //func(1,1.2,'@')
fn(10); //func(10,1.2,'@')
fn(20, 9.8); //func(20,9.8,'@')
fn(30, 3.5, '#'); //func(30,3.5,'#')
return (0);
}
字符串类型:string
C
:
- C 字符串是
char*
类型,是以'\0'
字符结束的字符数组。 - 在
C++
中处理C
字符串,使用#include <cstring>
C++
:
string
是类- 作为区别,用
cstring
称C
字符数组1
2
3
4string s1; // 默认构造
string s2 = "c plus plus"; // 用cstring构造
string s3 = s2; // 用同类对象构造
string s4 (5, 's'); // 用int,char作为参数构造
访问控制
公有成员
公有成员在客户端可以任意访问。
公有数据成员不需要通过公有函数成员访问,其优点是使用方便,缺点是可能会破坏封装的逻辑一致性。
私有成员
私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。
默认情况下,class的所有成员都是私有的。
实际操作中,一般会在私有区域定义数据,在公有区域定义相关的函数,以便在类的外部也可以调用这些函数,保持对象内部状态一致
构造/析构
无参构造函数
类的构造函数是类的一种特殊的成员函数,每次创建类的新对象时执行它完成初始化等逻辑。
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回
void
。如果用户没有自定义构造函数,则编译会自动生成一个默认构造函数
C++11
以后建议申明时写含参形式1
2
3
4
5
6
7
8
9
10
11
12
13class date {
private:
int year;
int month;
public:
date(int = 2023, int = 1);
};
date::date(int y, int m) {
year = y;
month = m;
}
含参构造函数
构造函数也可以带有参数。这样在创建对象时就可使用参数构造对象。
用户一旦定义了构造函数,编译器就不再自动添加默认构造函数。这时调用无参构造函数会报错
构造函数也能使用默认实参。这样可以减少构造函数重载的数量。
析构函数
类的析构函数是类的一种特殊的成员函数,它会在对象被释放前执行。
析构函数的名称与类的名称是相同的,只是在前面加
~
作为前缀,不会返回任何值,也不能带有参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
析构函数不能直接调用
this
指针
注意点
- 在
C++
中,每一个对象都能通过this
指针来访问自己的地址。this
指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。 - 当成员函数参数与成员数据重名时,必须使用
this
访问成员数据。 - 只有动态成员函数才有 this 指针。
- 友元函数没有
this
指针,因为友元不是类的成员。 static
成员不能使用this
,应使用::
。->
是指针取成员运算
示例
1 | class box { |
1 | int main(void) { |
Output:
1 | Constructor called. |