析构函数调用顺序,const型对象,对象函数共用

1. 析构函数的调用顺序:

单个对象创建时其构造函数的调用顺序:

      1. 调用父类的构造函数

      2. 调用内部成员变量的构造函数,变量间的调用顺序和声明顺序相同

      3. 调用自己的构造函数

多个或者单个对象销毁时其析构函数的调用顺序和构造函数相反

#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.Member()  mA.Member()  mB.Member()  Test.Test()
            // 析构顺序:Test.~Test() mB.~Member() mA.~Member() gA.~Member()
    return 0;
}

 

析构函数调用规则如下:

          1. 存在于栈和全局的对象在析构时:构造顺序和析构顺序相反。

          2. 存在于堆对象的对象在析构时:析构顺序域delect调用顺序相反。

 

2. const修饰的对象:

      const修饰的对象是只读对象(成员变量属性变为只读,成员函数属性不变)

const成员函数:

      const对象只可以调用const成员函数,不可调用对象中其他非const函数

      const成员函数中只能够调用const成员函数,不可调用对象中其他非const函数

      const成员函数不可以直接修改成员变量的值

const成员函数定义:

      Type ClassName::Function(Type p) const

      类中函数的声明和实际函数的定义都要带const关键字

#include <stdio.h>

class Test
{
    int mi;
public:
    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);
    printf("t.getMi()\n",t.getMi());  // error const成员只可以调用对象中的const成员函数
    return 0;
}

 

 3. 每个对象都有自己的一套成员变量(属性),所有的对象共享同一套成员函数(方法)。

  原因:代码段存放在代码段不可添加删除。变量存放于堆栈静态存储区可以添加删除。

    如何让方法访问对应对象的属性:成员函数(方法)中包含一个指针: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;
}
    
int Test::getMi()
{
    return mi;
}

void Test::print()
{
    printf("this = %p\n", this);
}

int main()
{
    Test t1(1);
    Test t2(2);
    Test t3(3);
    
    printf("t1.getMi() = %d\n", t1.getMi()); 
    printf("&t1 = %p\n", &t1);                    // addr1  this指针指向的地址是对象的首地址
    t1.print();                                   // addr1
    
    printf("t2.getMi() = %d\n", t2.getMi());
    printf("&t2 = %p\n", &t2);                    // addr2  addr1 与 addr2 地址不同说明每套对象都有不同的地址
    t2.print();                                   // addr2 
   
    printf("t3.getMi() = %d\n", t3.getMi());
    printf("&t3 = %p\n", &t3);                    // addr3
    t3.print();                                   // addr3
    
    return 0;
}

 

posted @ 2019-05-07 15:28  张不源  Views(466)  Comments(0Edit  收藏  举报