C++中的析构顺序和cosnt对象
1,当程序中存在多个对象的时候,如何确定这些对象的析构顺序?
2,单个对象创建时构造函数的调用顺序(工程经验总结):
1,调用父类的构造过程;
2,调用成员变量的构造函数(调用顺序与声明顺序相同);
1,某个类的成员是其它类的对象;
3,调用类自身的构造函数;
1,析构函数与对应构造函数的调用顺序相反;
3,多个对象析构时:
1,构造顺序与析构顺序相反;
4,构造与析构顺序实例分析:
#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; // gA
// mA
// mB
// Test()
// ...
//~Test()
// mB
// mA
// gA return ;
}
5,对于栈对象和全局对象,类似于入栈与出栈的顺序,最后构造的对象最先析构;堆对象的析构发生在使用 delete 的时候,与 delete 的顺序相关;
6,const 关键字能否修饰类的对象?如果可以,有什么特性?
1,const 关键字能够修饰对象;
1,类也是用户自定义的数据类型,类是从 struct 进化而得到的一个全新关键字,struct 专门用来定义结构体,其定义的结构体在 C 语言中依旧是变量,既然是变量,就可以被 cosnt 所修饰;
2,对应的,对象在某种角度也是变量,所以也可以被 const 修饰;
2,const 修饰的对象为只读对象;
1,这是唯一的可能性;
3,只读对象的成员变量不允许被改变;
1,对象就是由一系列的成员变量构成的,对象已经是只读的了,也就意味着成员变量是不允许被改变的;
4,只读对象是编译阶段的概念,运行时无效;
1,只读对象起始还是可以被改变的;
7,C++ 中的 const 成员函数:
1,const 对象只能调用 const 的员函数;
1,因为 const 对象的 this 指针是底层常量,不能拷贝给非 const 的成员函数的 this 指针,因为后者的 this 是变量,这会改变 const *this 的属性,造成其指向的对象会被改变;
2,const 成员函数中只能调用 const 成员函数;
1,底层 const 指针不能拷贝给非 const 指针;
3,const 成员函数中不能直接改写成员变量的值;
1,const 成员函数只能被 const 对象调用,而此时其成员函数也底层 const 的,不能修改底层 const 指针指向的变量;
4,const 成员函数特殊的意义是被只读对象调用;
1,底层 const 指针不能拷贝给非 const 指针;
8,const 成员函数的定义:
1,Type ClassName::function(Type p) const
1,声明之后,函数体之前;
2,类中的函数声明与实际函数定义中都必须带 const 关键字;
9,类的 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)
{
// mi = t.getMi(); getMi() 非常函时,t 是对象的常引用,t 这个对象代表的引用代表只读对象,只能调用 const 函数;
mi = t.mi; // 这个时候可以,mi 是私有的,能够通过点操作符来访问吗?不是说只有对象自己的成员函数才可以访问自己的成员变量吗?这就引出了本文10中的问题;
} int Test::getMi() const
{
// mi = 2; 这里出错,不能够修饰 mi 的值;
return mi;
} int main()
{
Test t(); const Test t1(); // 实际工程开发中,并不一定每一个成员函数都是 const 的,这就意味着很少使用 const 对象,所以 一般情况都不用定义 const 成员函数; t1.mj = ; // 不能给只读变量 mj 赋值;const 修饰对象后,得到只读对象,其对应的成员变量值是不可以被改变的;只读变量:编译阶段不能出现在赋值符号左边,运行时能够改变; printf("t.getMi() = %d\n", t.getMi()); // 编译器显示 getMi() 是不可以被调用的,因为这个时候 t 是只读对象,但是 getMi() 这个时候不是 const 函数,加上后则可以了; return ;
}
10,成员函数和成员变量都是隶属于具体对象的吗?
1,每一个对象都拥有自己的一套成员变量,但是所有的对象共享一套成员函数;
11,从面向对象的角度:
1,对象由属性(成员变量)和方法(成员函数)构成;
从程序运行的角度:
1,对象由数据和函数构成:
1,数据可以位于栈、堆和全局数据区;
2,函数只能位于代码段;
1,代码段是只读的,在程序运行过程中是不可以被改变的,当编译器将最终的可执行程序编译好之后,代码段就被确定了,不可以被该;
2,对象可以动态的创建、动态的删除,对于数据而言,可以做到,栈数据、堆数据都可以动态的创建出来、动态的删除掉,但对于代码不可能;
3,在面相对象里面,由于程序的特性,天生的决定了成员函数是不能每个对象都有一套的,只可能是所有的对象共享一套成员函数,因为代码段是不可以动态的添加和删除的;
12,结论:
1,每一个对象拥有自己独立的属性(成员变量);
2,所有的对象共享类的方法(成员函数);
3,方法能够直接访问对对象的属性;
4,方法中的隐藏参数 this 用于指代当前对象;
1,所有的对象都可以调用一套成员函数,函数本身如何知道是那个对象调用的呢?
2,成员函数(和普通函数区别在于其多了一个隐藏的参数 this)分辨不同对象通过 this 指针来分辨;
3,this 指针通过接受不同的对象传来的地址来给成员函数分辨对象;
1,所以 const 函数只能调用 const 函数是因为要传递个被调用对象的 this 指针,但是调用函数的底层 const this 指针只能拷贝给被调用对象的底层 const this 指针;
13,成员函数的秘密编程实验:
#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; // 成员函数可以直接访问成员变量,因此拷贝构造函数这个特殊的成员函数就可以直接访问对象的成员变量,所以这里直接访问了 t 这个引用所指代的对象的成员变量是完全合法的;成员函数只有一套,它能直接访问任何所属类对象的成员变量,当然被调用时只传递一个对象的地址; } int Test::getMi()
{
return mi;
} void Test::print()
{
printf("this = %p\n", this);
} int main()
{
Test t1();
Test t2();
Test t3(); printf("t1.getMi() = %d\n", t1.getMi()); //
printf("&t1 = %p\n", &t1); // t1 的地址
t1.print(); // t1 的地址 printf("t2.getMi() = %d\n", t2.getMi()); //
printf("&t2 = %p\n", &t2); // t2 的地址
t2.print(); // t2 的地址 printf("t3.getMi() = %d\n", t3.getMi()); //
printf("&t3 = %p\n", &t3); // t3 的地址
t3.print(); // t3 的地址 return ;
}
1,实验说明:
1,在类的成员函数当中,有一个隐含的参数,它是一个指针,并且这个指针的值就是调用这个函数所对应的对象的地址;
2,也就是 this 指针指向当前对象;
3,成员函数有一个隐含的参数,这个参数是一个 this 指针,其指向当前对象;
4,每一个对象都有一套自己的成员变量,对象和对象之间的成员变量是独立的、不同的;但是每一个对象都共享一个类的成员函数;
14,小结:
1,对象的析构顺序与构造顺序相反;
2,const 关键字能够修饰对象,得到只读对象;
3,只读对象只能调用 const 成员函数;
4,所有对象共享类的成员函数;
5,隐藏的 this 指针用于表示当前对象;
C++中的析构顺序和cosnt对象的更多相关文章
- C++解析(12):初始化列表与对象构造顺序、析构顺序
0.目录 1.类成员的初始化 2.类中的const成员 3.对象的构造顺序 3.1 局部对象的构造顺序 3.2 堆对象的构造顺序 3.3 全局对象的构造顺序 4.对象的析构顺序 5.小结 1.类成员的 ...
- MFC中成员变量的声明顺序与析构顺序
第一次用博客,第一篇随笔,就写今天遇到的一个问题吧. 在VS2008的MFC对话框程序,窗口成员变量的声明顺序与其析构顺序相反,即,先声明的变量后析构,后声明的变量先析构.未在其他模式下测试. cla ...
- C++浅析——继承类中构造和析构顺序
先看测试代码,CTEST 继承自CBase,并包含一个CMember成员对象: static int nIndex = 1; class CMember { public: CMember() { p ...
- Promise对象及它在js中的执行顺序
关于Promise对象的学习及它的执行顺序 学习阮一峰老师的ES6入门后的记录 1.promise的定义 promise是一个对象,通常包裹着一个异步操作,promise对象提供一些接口的方法,返回一 ...
- JS对象 颠倒数组元素顺序reverse() reverse() 方法用于颠倒数组中元素的顺序。
颠倒数组元素顺序reverse() reverse() 方法用于颠倒数组中元素的顺序. 语法: arrayObject.reverse() 注意:该方法会改变原来的数组,而不会创建新的数组. 定义数组 ...
- C++语法小记---继承中的构造和析构顺序
继承中构造和析构的顺序 先父母,后客人,最后自己 静态变量和全局变量在最开始 析构和构造的顺序完全相反 #include <iostream> #include <string> ...
- C++ //继承中构造和析构顺序
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 class Base 6 { 7 pu ...
- iOS 中的 block 是如何持有对象的
Block 是 Objective-C 中笔者最喜欢的特性,它为 Objective-C 这门语言提供了强大的函数式编程能力,而最近苹果推出的很多新的 API 都已经开始原生的支持 block 语法, ...
- Effective C++学习笔记:初始化列表中成员列出的顺序和它们在类中声明的顺序相同
类成员的默认初始化顺序是按照声明顺序进行, 如果使用初始化列表初始化成员变量, 则必须按照成员变量的声明顺序进行; 否则, 在变量之间交替赋值时, 会产生, 未初始化的变量去赋值其他变量; 同时GCC ...
随机推荐
- 6.re正则表达式
import re import unicodedata s = "a00xoghasalexjkdfldhfjk" v = s.find("alex") pr ...
- C# 泛型 new{ }??? //加new 和不加new 有什么不同? new() 约束
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- Java面试题系列(七)锁的原理
redis实现分布式锁 synchronized 和 reentrantlock的区别,偏向锁/轻量级锁/重量级锁的原理,能否从偏向锁直接升级成重量级锁
- UVa 122 Trees on the level (动态建树 && 层序遍历二叉树)
题意 :输入一棵二叉树,你的任务是按从上到下.从左到右的顺序输出各个结点的值.每个结 点都按照从根结点到它的移动序列给出(L表示左,R表示右).在输入中,每个结点的左 括号和右括号之间没有空格,相邻 ...
- OverFeat:基于卷积网络的集成识别、定位与检测
摘要:我们提出了一个使用卷积网络进行分类.定位和检测的集成框架.我们展示了如何在ConvNet中有效地实现多尺度和滑动窗口方法.我们还介绍了一种新的深度学习方法,通过学习预测对象边界来定位.然后通过边 ...
- Linux系统设置开机自动启动ORACLE数据库服务
具体方法如下: 1. 修改oratab (root用户执行) /etc/oratab的配置格式如下: $ORACLE_SID:$ORACLE_HOME:Y 2. 测试dbstart, dbstop(o ...
- 京东面试题:Java中 ++i 的操作是线程安全的么?为什么?如何使其线程安全呢?
你真的了解volatile关键字吗?http://blog.csdn.net/FansUnion/article/details/79495080 面试题:为什么最后两行没有运行?http://blo ...
- mongoose 创建自增字段方法
first: create counter collection in mongodb:> db.counters.insert({_id:"entityId",seq:0} ...
- c/c++运算符
1.算术运算符(+ - / * %) 2.移位运算符 移运算符:操作数必须是整形,>>,逻辑左移左边移入的位用0填充,算数左移左边移入的的位用符号位补齐.(无符号数为逻辑左移,对于 ...
- @清晰掉 GDB调试器中的战斗机
GDB 的命令很多,本文不会全部介绍,仅会介绍一些最常用的.在介绍之前,先介绍GDB中的一个非常有用的功能:补齐功能.它就如同Linux下SHELL中的命令补齐一样.当你输入一个命令的前几个字符,然后 ...