C++——析构函数的调用顺序、const修饰对象、类成员

1.析构顺序和构造顺序

(1)单个对象创建时构造函数的调用顺序

①调用父类的构造过程 ②调用成员变量的构造函数(调用顺序与声明顺序相同)③调用类自身的构造函数

析构函数与对应构造函数的调用顺序相反 :③②①

(2)示例:

复制代码
#include <stdio.h>
class Member {
	const char* ms;
public:
	Member(const char* s) {
		printf("Member(const char* s):%s\n", s);
		ms = s;
	}
	~Member() {
		printf("~Member():%s\n", ms);
	}
};
class Test {
	Member mA;
	Member mB;
public:
	Test() :mB("mB"), mA("mA") {
		printf("Test()\n");
	}
	~Test() {
		printf("~Test()\n");
	}
};
Member gA("gA");

int main() {
	Test t; 
	return 0;
}

运行结果:

(3)析构顺序

①对于栈对象和全局对象,类似于入栈和出栈的顺序,最后构造的对象被最先析构

⑤堆对象的析构发生在使用delete的时候,与delete的使用顺序相关

2.const修饰对象

(1)const关键字能够修饰对象

(2)const修饰的对象为只读对象

(3)只读对象的成员变量不允许被改变

(4)只读对象是编译阶段的概念,运行时无效

(5)const对象只能调用const成员函数,const成员函数中只能调用const成员函数,const成员函数中不能直接改写成员变量的值

复制代码
#include <stdio.h>
class Test {
	int mi;
public:
	int mj;
	Test(int i);
	Test(const Test& t);
	int getMi();
};
Test::Test(int i) {
	mi = i;
}
Test::Test(const Test& t) {

}
int Test::getMi() {
	return mi;
}
int main() {
	const Test t(1);
	// t.mj = 1000; 报错,因为t是只读对象,不能修改成员变量的值
	
	//printf("t.getMi()=%d\n", t.getMi()); 报错,因为t是const对象,只能调用const成员函数
	return 0;
}

如果想要调用getMi()函数,则需要将该成员函数变为const函数

复制代码
#include <stdio.h>
class Test {
	int mi;
public:
	int mj;
	Test(int i);
	Test(const Test& t);
	int getMi()const;
};
Test::Test(int i) {
	mi = i;
}
Test::Test(const Test& t) {

}
int Test::getMi()const {
	return mi;
}
int main() {
	const Test t(1);
	// t.mj = 1000; 报错,因为t是只读对象,不能修改成员变量的值
	
	printf("t.getMi()=%d\n", t.getMi()); // t.getMi()=1
	return 0;
}

(1)从面向对象的角度,对象由属性(成员变量)和方法(成员函数)构成

(2)从程序运行的角度,对象由数据和函数构成,数据可以位于栈、堆和全局数据区中,函数只能位于代码段中

结论:

(1)每一个对象拥有自己独立的属性(成员变量)

(2)所有的对象共享类的方法(成员函数)

(3)方法能够直接访问对象的属性

(4)方法中的隐藏参数 this用于指代当前对象

复制代码
#include <stdio.h>
class Test {
	int mi;
public:
	int mj;
	Test(int i);
	Test(const Test& t);
	int getMi();
	void print();
};
Test::Test(int i) {
	mi = i;
}
Test::Test(const Test& t) {
	mi = t.mi; //mi是私有属性,但是仍可访问,因为Test(const Test& t)是成员函数,可以访问对应对象的成员变量
}
int Test::getMi() {
	return mi;
}
void Test::print() {
	printf("this=%p\n", this); //this指针指向当前调用该函数的对象地址
}
int main() {
	Test t1(1); 
	Test t2(2);
	Test t3(3);
	
	printf("t1.getMi()=%d\n", t1.getMi());
	printf("&t1=%p\n", &t1);
	t1.print();
	printf("t2.getMi()=%d\n", t2.getMi());
	printf("&t2=%p\n", &t2);
	t2.print();
	printf("t3.getMi()=%d\n", t3.getMi());
	printf("&t3=%p\n", &t3);
	t3.print();
	return 0;
}

运行结果:

相关推荐
峥无4 分钟前
C++11 深度详解:现代 C++ 基石全梳理
开发语言·c++·笔记
阿米亚波15 分钟前
【C++ STL】std::unordered_multimap
开发语言·数据结构·c++·笔记·stl
小王C语言38 分钟前
【3. 基于 Vibe Coding 的 OJ 平台】. 构建仓库、环境准备、需求梳理、安装依赖
网络·c++
SomeB1oody1 小时前
【RustyML入门】1.0. 快速上手
开发语言·后端·机器学习·rust·教程
狗凯之家源码网1 小时前
短剧系统搭建实战:源码功能与商业变现效果全景展示
开发语言·php
小王C语言1 小时前
【8.进行接口测试】:通过 curl 进行接口自动化测试 / 通过 python 程序进行接口自动化测试
网络·c++
易筋紫容2 小时前
创建型模式:对象的诞生艺术
开发语言·前端·javascript
888CC++2 小时前
C++ 快速学习指南:从入门到进阶的实战路线
开发语言·c++
小小晓.2 小时前
C++记:函数
开发语言·c++·算法
牡丹雅忻13 小时前
AES 加密模式演进:从 ECB、CBC 到 GCM 的 C# 深度实践
java·开发语言·c#