第24课.经典问题解析(1.析构函数的顺序;2.const修饰对象;3.成员函数,成员变量是否属于具体对象)

1.当程序中存在多个对象的时候,如何确定这些对象的析构顺序?

单个对象

单个对象创建时构造函数的调用顺序
a.调用父类的构造函数
b.调用成员变量的构造函数(调用顺序与声明顺序相同)
c.调用类自身的构造函数

析构函数与对应的构造函数的调用顺序相反

多个对象

多个对象时,析构函数与构造顺序相反

eg:这端代码就可以解释上述

#include <stdio.h>

class Member
{
    const char *ms;        //这里是const指针
    
public:
    Member(const char *s)
    {
        printf("Member(const char* s): %s
", s);

        ms = s;        //因为上述被定义为指针所以这里才能间接的去修改。
    }
    
    ~Member()
    {
        printf("~Member(): %s
", ms);
    }
};

class Test
{
    Member mA;
    Member mB;
 
 public:
    Test() : mB("mB"), mA("mA")
    {
        printf("Test()
");
    }
    
    ~Test()
    {
        printf("~Test()
");
    }
};

Member gA("gA");

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

对于栈对象和全局对象,类似于入栈和出栈的顺序,最后构造的对象最先构造
堆对象的析构发生在使用delete的时候,与delete的使用顺序相关

2.const关键字能否修饰类的对象?如果可以,有什么特性?

const对象

a.const关键字能够修饰对象
b.const修饰的对象为只读对象
c.只读对象的成员变量不能直接被改变(因为它的变量成了只读变量)
d.只读对象是编译阶段的概念,运行时无效

const成员函数

a.const对象只能调用const成员函数
b.const成员函数中只能调用const成员函数
c.const成员函数中不能直接改写成员变量的值 (因为它的变量成了只读变量)

const成员函数的定义:在函数的后面,函数体之前加上const关键字。
类中的函数声明和实际的函数定义中都必须带const关键字。

Type ClassName::function(Type p) const

const成员变量(20课,放在这里是为了对比学习)

a.类中的const成员变量会被分配空间
b.类中的const成员变量的本质是只读变量
c.类中的const成员变量只能在初始化列表中指定初始值(当然了指针类的可以间接去修改,见本课第一个例子)
(编译器无法直接得到const成员变量的初始值,因此无法进入符号表成为真正意义上的常量)

#include <stdio.h>

class Test
{
    int mi;
    
public:
    int mj;
    Test(int i);
    Test(const Test& t);
    int getMi() const;      //const函数
};

Test::Test(int i)
{
    mi = i;
}

Test::Test(const Test& t)
{
    //如果去掉int getMi() const;的const使他成为一个普通到成员函数时使用下面语句是否合法 (此时函数到定义也要去掉相应到const)    
    mi = t.getMi();         //不合法,因为const Test& t表明t是const对象,所以t只能调用const函数。        
}

int Test::getMi() const
{
    //mi = 2;       //不合法
    return mi;
}

int main()
{
    const Test t(1);        //const对象
    
    printf("t.getMi() = %d
", t.getMi());       //注意函数的使用不带const
    
    return 0;
}

3.成员函数和成员变量都是隶属于具体对象的吗?

a.从面向对象的角度来看
对象有属性(成员变量)和方法(成员函数)构成
b.从程序运行的角度
对象有数据(可以位于栈,堆,全局数据区)和函数构成(只能位于代码段)

结论:

a.每个对象都拥有自己的独立属性(成员变量)
b.所有的对象共享类的方法(成员函数)
c.成员函数能够直接访问对象的属性
d.成员函数中有隐藏参数this用于指代当前对象(共享的成员函数是怎么分辨是哪个对象在调用它呢?this参数会记录当前对象的地址)

Test::Test(const Test& t)
{  
    //这里来源于上述例子中,稍做修改。是否合法?t.mi是private怎么能被这样t.mi把它拿出来使用?
    mi = t.mi;          //合法,因为mi是类的成员变量。并且t.mi在拷贝函数中使用(特殊的成员函数)。成员函数能够直接访问对象的属性。     
}
原文地址:https://www.cnblogs.com/huangdengtao/p/11843071.html