C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

时间:2022-09-09 16:54:06

// 同类之间无私处

 

2构造函数

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

3析构函数

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

4构造函数的种类和析构函数的顺序

结论:析构函数的调用顺序,跟对象的构造顺序相反,谁先构造,谁最后一个被析构。

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

拷贝构造函数:

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

注意: 等号写在下面和写在上面是完全不同的。

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

 

5拷贝构造函数调用的发生场景

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

(注意这种情况的执行顺序, 在func函数执行的时候,调用了局部变量的拷贝构造函数

 

 C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

场景四:

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

 

using namespace std;

 

 

class Test

{

public:

    // 默认构造函数,就是一个无参数的构造函数,

    // 如果不显示提供构造函数 系统就是调用默认的构造函数 里面是空函数

    // 如果我们提供了一个显示的构造函数,那么默认的构造函数就被隐藏掉了。

 

    /*

        Test(){} 默认的构造函数,已经手动提供,默认就被隐藏

    */

 

    // 如果我们提供了一个显示的构造函数 那么默认的构造函数就被隐藏掉了

    // 构造函数一旦手动提供 默认将不复存在

    Test(int x, int y)

    {

        m_x = x;

        m_y = y;

        cout << "调用了有参数的构造函数" << endl;

    }

 

    // 无参数的构造函数

    Test()

    {

        m_x = 0;

        m_y = 0;

        cout << "调用了无参数的构造函数" << endl;

    }

 

 

    // 拷贝构造函数 想通过另一个Test对象 another 将本对象进行拷贝

    Test(const Test & another)

    {

        m_x = another.m_x;

        m_y = another.m_y;

        cout << "调用了拷贝构造函数" << endl;

    }

 

 

    // 等号操作符

    void operator = (const Test & t)

    {

        m_x = t.m_x;

        m_y = t.m_y;

    }

 

 

    void printT()

    {

        cout << "x: " << m_x << " ,y = " << m_y << endl;

    }

 

    // 提供一个析构函数

    ~Test()

    {

        cout << "~Test() 析构函数被执行了" << endl;

        cout << "(" << m_x << "," << m_y << ")" << "被析构了" << endl;

    }

 

private:

    int m_x;

    int m_y;

};

 

 

// 拷贝构造函数的第一个场景

void test1()

{

    Test t1(1, 2);

    Test t2(t1);

    // 通过t1 给t2 进行赋值

 

    t2.printT();

}

 

// 拷贝构造函数的第二个场景

void test2()

{

    Test t1(1, 2);

    Test t2;

    t2 = t1; //调用的不是拷贝构造函数, 调用的是 =号操作符,也能够完成将t1的值给t2

            // 但不是调用t2的拷贝构造函数

}

 

 

 

// 拷贝构造函数的第三个场景

void func(Test t) // Test t = test1::t1; // 会调用局部变量t的靠别构造函数

{

    cout << "func begin..." << endl;

    t.printT();

    cout << "func end..." << endl;

}

 

void test3()

{

    cout << "test3 begin ..." << endl;

    Test t1(10, 20); //创建了一个t1的对象 通过t1的有参数的构造函数

    func(t1);

    cout << "test3 end..." << endl;

}

 

 

// 场景四

Test func2()

{

    cout << "func2 begin..." << endl;

    Test temp(10, 20);

    cout << "func2 end.." << endl;

 

    return temp; //有一个临时的匿名对象 = temp , 把temp的数据给到了临时的匿名对象

                 // 会调用这个临时匿名对象的拷贝构造函数 把temp传进去。

}

 

 

void test4() {

    cout << "test4 begin..." << endl;

    func2();

 

    // 匿名对象在此被析构了 如果一个匿名的临时对象 没有任何变量去接受它

    // 编译器认为这个临时匿名对象没有用处

    // 编译器会立刻销毁这个临时的匿名对象

 

 

    cout << "test4 begin..." << endl;

}

 

int main(void)

{

    test4();

 

    return 0;

}

 

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

 C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

(红圈表示匿名函数析构)

 

6默认构造函数和深拷贝浅拷贝

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

 C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

 

7中午回顾

// 浅拷贝析构的时候 可能会出现问题重复析构 两次 引出问题

 

8构造函数的初始化列表

 C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

 结论:

// 类内部  的对象初始化的顺序  跟 对象定义的顺序一样 跟初始化列表中的顺序无关

// 析构的顺序就跟构造的顺序相反

 

 9 强化练习1

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

12new和delete

 

new 和 delete

malloc 和 free

 

在堆上分配和释放的时候功能是类似的。

 

区别:new和delete会调用构造函数和析构函数

malloc和free不会

 

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

 

using namespace std;

 

 

class Test

{

public:

    Test()

    {

        m_a = 0;

        m_b = 0;

        cout << "0,0 构造" << endl;

    }

    Test(int a, int b)

    {

        m_a = a;

        m_b = b;

        cout << "a = " << m_a << ", b = " << m_b << "构造" << endl;

    }

 

    void setA(int a)

    {

        m_a = a;

    }

 

    void setB(int b)

    {

        m_b = b;

    }

 

    void printT()

    {

        cout << "a = " << m_a << ", b =" << m_b << endl;

    }

 

    ~Test()

    {

        cout << "a = " << m_a << ", b = " << m_b << "析构" << endl;

    }

private:

    int m_a;

    int m_b;

};

 

 

 

// C语言中

void test1()

{

    int *p = (int *)malloc(sizeof(int));

    *p = 10;

    cout << *p << endl;

 

    if (p != NULL) {

        //free(p);

        delete p; // delete可以释放malloc开辟的内存

    }

   

 

    int *array_p = (int *)malloc(sizeof(int) * 10);

    for (int i = 0; i < 10; i++)

    {

        array_p[i] = i + 10;

    }

 

    for (int i = 0; i < 10; i++)

    {

        cout << array_p[i] << endl;

    }

 

    if (array_p != NULL)

    {

        free(array_p);

    }

   

    cout << " ------- " << endl;

 

    Test *tp = (Test *)malloc(sizeof(Test));// 不会调用对象的构造函数

 

    tp->setA(10);

    tp->setB(20); // malloc 出来的对象指针,只能够通过成员函数来进行初始化

    tp->printT();

 

    if (tp != NULL)

    {

        free(tp); //不会调用对象的析构

    }

 

}

 

 

 

// malloc 和 free 在对于普通变量是可以混合使用的 但是malloc和free是函数

// new和delete是操作符。不是一个函数(没有压栈出栈过程)

 

 

// C++中的new delete

void test2()

{

    //new 能够完成所有malooc的需求

    int *p = new int; // 在堆上动态开辟4个字节

    *p = 10;

    cout << *p << endl;

 

    if (p != NULL)

    {

        //delete p; //delete一个变量

        free(p); //用new开辟的内存 free也能够释放

    }

 

 

    cout << "----" << endl;

 

    int *array_p = new int[10];

 

    for (int i = 0; i < 10; i++)

    {

        array_p[i] = i + 10;

    }

 

 

    for (int i = 0; i < 10; i++)

    {

        cout << array_p[i] << endl;

    }

   

 

    if (array_p != NULL)

    {

        delete[] array_p; // delete一个数组

    }

 

    cout << "------" << endl;

    //Test *tp2 = new Test(10, 20); // 调用了有参数的构造函数//new 在创建一个对象的时候会调用对象的构造函数

    Test *tp2 = new Test; //调用了无参构造函数

    tp2->printT();

    if (tp2 != NULL)

    {

        delete tp2; // delete在释放一个对象指针的时候 会调用对象的析构函数

    }

}

 

 

int main(void)

{

    //test1();

 

    test2();    

    return 0;

}

 

13静态成员变量

 

在C语言中

static如果修饰全局变量 该变量不可以被别的文件访问

           修饰局部变量 生命周期随着生命周期销毁销毁

                 修饰函数:

                         (普通 函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。因此定义静态函数有以下好处:
  <1> 其他文件中可以定义相同名字的函数,不会发生冲突。
  <2> 静态函数不能被其他文件所用。)

 

(static 貌似是在编译的时候就确定的,不是运行时)

 

复习:

https://www.cnblogs.com/getyoulove/p/3656184.html

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

 C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

共享同一块静态区域

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

 

14 static成员变量练习

 

定义 Box 所有的高度都一样

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

(通过查看大小 说明static修饰的成员变量不属于对象中,而是在全局区开辟的)

 

15 static修饰成员函数

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

main函数中:

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

(这里没有对象,是直接用类调用的)

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

 

16 static总结和static成员变量的大小

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

 

 C++基础 (3) 第三天 构造函数 构造函数初始化列表 拷贝构造函数 析构函数 静态成员变量

结论:决定类大小的就是类的普通成员变量 没有函数和全局变量

 

明天讲为什么