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

运行结果:

相关推荐
cpp_250120 小时前
P1024 [NOIP 2001 提高组] 一元三次方程求解
数据结构·c++·算法·题解·二分答案·洛谷·csp
Gofarlic_oms11 天前
利用API实现ANSYS许可证管理自动化集成
运维·服务器·开发语言·matlab·自动化·负载均衡
AI+程序员在路上1 天前
VS Code 完全使用指南:下载、安装、核心功能与 内置AI 编程助手实战
开发语言·人工智能·windows·开源
invicinble1 天前
这里对java的知识体系做一个全域的介绍
java·开发语言·python
catchadmin1 天前
使用 PHP TrueAsync 改造 Laravel 协程异步化的可行路径
开发语言·php·laravel
wbs_scy1 天前
【Linux 线程进阶】进程 vs 线程资源划分 + 线程控制全详解
java·开发语言
AI人工智能+电脑小能手1 天前
【大白话说Java面试题】【Java基础篇】第15题:JDK1.7中HashMap扩容为什么会发生死循环?如何解决
java·开发语言·数据结构·后端·面试·哈希算法
郑州光合科技余经理1 天前
同城O2O海外版二次开发实战:从支付网关到配送算法
开发语言·前端·后端·算法·架构·uni-app·php
南子北游1 天前
Python学习(基础语法1)
开发语言·python·学习
张健11564096481 天前
使用信号量限制并发数量
开发语言·c++