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

运行结果:

相关推荐
无尽的沉默1 小时前
Thymeleaf 表达式
java·开发语言·前端
Java后端的Ai之路1 小时前
【JDK】-JDK 11 新特性内容整理(很全面)
java·开发语言·后端·jdk
czxyvX1 小时前
010-C++11
开发语言·c++
水饺编程2 小时前
第4章,[标签 Win32] :TextOut 测试案例2
c语言·c++·windows·visual studio
亓才孓2 小时前
【MyBatis Plus】Wrapper接口
java·开发语言·数据库·spring boot·mybatis
tianzhiyi1989sq2 小时前
C++工具库之PugiXML使用指南
java·数据库·c++
游乐码2 小时前
c#运算符重载
开发语言·c#
人道领域2 小时前
MyBatisPlus高效开发实战指南
java·开发语言·数据库
tankeven2 小时前
HJ98 喜欢切数组的红
c++·算法