c++-构造函数

2019-12-21 16:01:23来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

c++-构造函数

构造函数

  • 构造和析构概念语法
  • 构造函数的分类
  • 有参构造函数3种调用方法
  • 拷贝构造函数4种调用时机
    • 场景1和2:A a(b); A a = b;
    • 场景3:形参是一个元素,实参传递给形参
    • 场景4:函数返回值返回一个元素,匿名对象
    • 匿名对象的去和留
    • 对象的初始化 和 对象的=操作 是两个不同的概念
  • 构造和析构
    • 构造和析构概念语法
    • 构造函数的分类
    • 有参构造函数3种调用方法
    • 拷贝构造函数4种调用时机
      • 场景1和2:A a(b); A a = b;
      • 场景3:形参是一个元素,实参传递给形参
      • 场景4:函数返回值返回一个元素,匿名对象
      • 匿名对象的去和留
      • 对象的初始化 和 对象的=操作 是两个不同的概念
    • 构造函数调用规则研究(写了构造函数则必须调用)
    • 多个对象的构造 构造函数初始化列表
    • 构造函数和析构函数的调用顺序(先组合对象的构造、自己构造;析构和构造相反)
    • 深拷贝和浅拷贝
      • 问题抛出 显示的编写拷贝构造函数
      • 默认的=号操作 也是浅拷贝,解决方案重载=操作符
      • 总结:C++编译给提供的默认的拷贝构造和=操作都是浅拷贝
    • 构造和析构综合练习
      • 匿名对象:直接调用构造函数
      • 匿名对象:构造中调用构造
  • 构造函数调用规则研究(写了构造函数则必须调用)
  • 多个对象的构造 构造函数初始化列表
  • 构造函数和析构函数的调用顺序(先组合对象的构造、自己构造;析构和构造相反)
  • 深拷贝和浅拷贝
    • 问题抛出 显示的编写拷贝构造函数
    • 默认的=号操作 也是浅拷贝,解决方案重载=操作符
    • 总结:C++编译给提供的默认的拷贝构造和=操作都是浅拷贝
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>


using namespace std;

class Test
{
public:
#if 0
    void init(int x, int y)
    {
        m_x = x;
        m_y = y;
    }
#endif

    //test类的构造函数
    //在对象被创建的时候,用来初始化对象的函数
    Test()//无参数的构造函数
    {
        m_x = 0;
        m_y = 0;
    }
    Test(int x, int y)
    {
        m_x = x;
        m_y = y;
        // name = (char*)malloc(100);
        strcpy(name, "zhang3");
    }
    Test(int x)
    {
        m_x = x;
        m_y = 0;
    }

    void printT()
    {
        cout << "x = " << m_x << "  y = " << m_y << endl;
    }


    //析构函数和构造函数都没有返回值,
    //析构函数没有形参
    ~Test() {
        cout << "~Test()...." << endl;
        if (name != NULL) {
            // free(name);
            cout << "free succ!" << endl;
        }
    }
private:
    int m_x;
    int m_y;
    char *name;
};

void test1()
{
    Test t1(10, 20);
    t1.printT();

    //在一个对象临死之前,要自定调用析构函数
}

int main(void)
{
#if 0
    Test t1(10, 20);
    t1.printT();
    //t1.init(10, 20);

    Test t2(100);
    t2.printT();

    Test t3;//就是调用类的无参数构造函数

    t3.printT();

#endif

    test1();
    return 0;
}

拷贝构造函数

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>


using namespace std;

class Test
{
public:
    Test()
    {
        m_x = 0;
        m_y = 0;
    }
    Test(int x, int y)
    {
        m_x = x;
        m_y = y;
    }

    void printT()
    {
        cout << "x =" << m_x << ", y = " << m_y << endl;
    }

#if 1
    //显示的拷贝构造函数
    Test(const Test &another)
    {
        cout << "Test(const Test &)..." << endl;
        m_x = another.m_x;
        m_y = another.m_y;
    }
#endif
#if 0
    //? 会有一个默认的拷贝构造函数
    Test(const Test &another)
    {
        m_x = another.m_x;
        m_y = another.m_y;
    }
#endif

    //=赋值操作符
    void operator=(const Test &another)
    {
        m_x = another.m_x;
        m_y = another.m_y;
    }
private:
    int m_x;
    int m_y;
};

int main(void)
{
    Test t1(100, 200); 

    Test t2(t1); 

    t2.printT();



    //构造函数是对象初始化的时候调用
    Test t3; //依然是初始化t3的时候调用t3构造函数,依然是调用t3的拷贝构造函数

    t3 = t1; //调用的不是t3拷贝构造函数,而是t3的赋值操作符函数

    return 0;
}

默认的构造函数和解析构造函数

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>


using namespace std;

class Test
{
public:
    //默认的无参构造函数
#if 0
    Test()
    {

    }
#endif
    //显示提供一个有参数的构造函数,默认的构造函数就不复存在
    Test(int x, int y)
    {
        m_x = x;
        m_y = y;
    }
    Test() {
        m_x = 0;
        m_y = 0;
    }

    void printT()
    {
        cout << "x = " << m_x << "  y = " << m_y << endl;
    }

    //默认的析构函数
#if 0
    ~Test()
    {

    }
#endif
    ~Test() {
        cout << "~Test()..." << endl;
    }


private:
    int m_x;
    int m_y;
};

int main(void)
{
    Test t1;//调用Test无参构造
    t1.printT();
    
    return 0;
}

默认的拷贝构造函数

  • 类中 会有个默认的无参构造函数:

当没有任何显示的构造函数(显示的无参构,显示有参,显示拷贝构造) 的时候,默认无参构造函数就会出现。

  • 会有默认的拷贝构造函数:
    -->当没有 显示的拷贝构造 * 的函数,默认的拷贝构造就会出现。

  • 会有默认的析构函数
    --> 当没有显示的析构函数的时候, 默认的析构函数就会出现

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>

using namespace std;

class A
{
public:
#if 0
    A()
    {
        
    }
#endif
#if 0
    A(const A &another)
    {
        m_a = another.m_a;
        m_b = another.m_b;
    }
#endif
    A()
    {

    }
    A(int a, int b)
    {

    }
#if 0
    ~A()
    {

    }
#endif
    ~A()
    {
        cout << "~A()" << endl;
    }
private:
    int m_a;
    int m_b;
};

//类中 会有个默认的无参构造函数:  、
//      -->当没有任何***显示的构造函数(显示的无参构,显示有参,显示拷贝构造)*** 的时候,默认无参构造函数就会出现。

//      会有默认的拷贝构造函数:
//      -->当没有 **显示的拷贝构造 ***  的函数,默认的拷贝构造就会出现。

//     会有默认的析构函数
//      --> 当没有***显示的析构函数***的时候,  默认的析构函数就会出现。


int main(void)
{
    A a;
    
    A a1(a);
    
    return 0;
}

拷贝构造函数的应用场景

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>

using namespace std;

class Test
{
public:
    Test()
    {
        cout << "test()..." << endl;
        m_x = 0;
        m_y = 0;
    }
    Test(int x, int y)
    {
        cout << "Test(int x, int y)..." << endl;

        m_x = x;
        m_y = y;
    }
    Test(const Test & another)
    {
        cout << "Test(const Test &)..." << endl;
        m_x = another.m_x;
        m_y = another.m_y;
    }

    void operator=(const Test &another)
    {
        cout << "operatoer = (const Test &)" << endl;
        m_x = another.m_x;
        m_y = another.m_y;
    }

    void printT() {
        cout << "x = " << m_x << ", m_y = " << m_y << endl;
    }

    ~Test() {
        cout << "~Test()..." << endl;
    }
private:
    int m_x;
    int m_y;
};


//析构函数调用的顺序, 跟构造相反, 谁先构造的,谁后析构。
//场景1
void test1()
{
    Test t1(10, 20);
    Test t2(t1);//Test t2 = t1;
}

//场景2
void test2()
{
    Test t1(10, 20);
    Test t2;

    t2 = t1;//=操作符
}


void func(Test t)//Test t = t1; //Test t 的拷贝构造函数
{
    cout << "func begin..." << endl;
    t.printT();
    cout << "func end..." << endl;
}

//场景3
void test3()
{
    cout << "test3 begin..." << endl;
    Test t1(10, 20);

    func(t1);

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


//场景4
Test func2()
{
    cout << "func2 begin..." << endl;
    Test temp(10, 20);
    temp.printT();

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

    return temp;
}//匿名的对象 = temp  匿名对象.拷贝构造(temp)

void test4()
{
    cout << "test4 being.. " << endl;
    func2();// 返回一个匿名对象。 当一个函数返回一个匿名对象的时候,函数外部没有任何
            //变量去接收它, 这个匿名对象将不会再被使用,(找不到), 编译会直接将个这个匿名对象
            //回收掉,而不是等待整改函数执行完毕再回收.
    //匿名对象就被回收。
    
    cout << "test4 end" << endl;
}

void test5()
{
    cout << "test 5begin.. " << endl;
    Test t1 = func2(); //会不会触发t1拷贝构造来   t1.拷贝(匿名)?
                        //并不会触发t1拷贝,而是 将匿名对象转正 t1,
                        //把这个匿名对象 起了名字就叫t1.

    cout << "test 5 end.." << endl;
}

//场景6
void test6()
{
    cout << "test6 begin..." << endl;
    Test t1;//t1已经被初始化了。

    t1 = func2(); //t1已经被初始化了,所以func2返回的匿名对象不会再次转正,而依然是匿名对象。
                    //所以t1会调用等号操作符,t1.operator=(匿名对象), 然后编译器会立刻回收掉匿名对象

    t1.printT();

    cout << "test6 end.." << endl;
}


int main(void)
{
    //test1();
    //test2();
    //test3();
    //test4();
    //test5();
    test6();

    return 0;
}

深拷贝和浅拷贝

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>

using namespace std;

class Test
{
public:
    Test()
    {
        cout << "test()..." << endl;
        m_x = 0;
        m_y = 0;
    }
    Test(int x, int y)
    {
        cout << "Test(int x, int y)..." << endl;

        m_x = x;
        m_y = y;
    }
    Test(const Test & another)
    {
        cout << "Test(const Test &)..." << endl;
        m_x = another.m_x;
        m_y = another.m_y;
    }

    void operator=(const Test &another)
    {
        cout << "operatoer = (const Test &)" << endl;
        m_x = another.m_x;
        m_y = another.m_y;
    }

    void printT() {
        cout << "x = " << m_x << ", m_y = " << m_y << endl;
    }

    ~Test() {
        cout << "~Test()..." << endl;
    }
private:
    int m_x;
    int m_y;
};


//析构函数调用的顺序, 跟构造相反, 谁先构造的,谁后析构。
//场景1
void test1()
{
    Test t1(10, 20);
    Test t2(t1);//Test t2 = t1;
}

//场景2
void test2()
{
    Test t1(10, 20);
    Test t2;

    t2 = t1;//=操作符
}


void func(Test t)//Test t = t1; //Test t 的拷贝构造函数
{
    cout << "func begin..." << endl;
    t.printT();
    cout << "func end..." << endl;
}

//场景3
void test3()
{
    cout << "test3 begin..." << endl;
    Test t1(10, 20);

    func(t1);

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


//场景4
Test func2()
{
    cout << "func2 begin..." << endl;
    Test temp(10, 20);
    temp.printT();

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

    return temp;
}//匿名的对象 = temp  匿名对象.拷贝构造(temp)

void test4()
{
    cout << "test4 being.. " << endl;
    func2();// 返回一个匿名对象。 当一个函数返回一个匿名对象的时候,函数外部没有任何
            //变量去接收它, 这个匿名对象将不会再被使用,(找不到), 编译会直接将个这个匿名对象
            //回收掉,而不是等待整改函数执行完毕再回收.
    //匿名对象就被回收。
    
    cout << "test4 end" << endl;
}

void test5()
{
    cout << "test 5begin.. " << endl;
    Test t1 = func2(); //会不会触发t1拷贝构造来   t1.拷贝(匿名)?
                        //并不会触发t1拷贝,而是 将匿名对象转正 t1,
                        //把这个匿名对象 起了名字就叫t1.

    cout << "test 5 end.." << endl;
}

//场景6
void test6()
{
    cout << "test6 begin..." << endl;
    Test t1;//t1已经被初始化了。

    t1 = func2(); //t1已经被初始化了,所以func2返回的匿名对象不会再次转正,而依然是匿名对象。
                    //所以t1会调用等号操作符,t1.operator=(匿名对象), 然后编译器会立刻回收掉匿名对象

    t1.printT();

    cout << "test6 end.." << endl;
}


int main(void)
{
    //test1();
    //test2();
    //test3();
    //test4();
    //test5();
    test6();

    return 0;
}

构造函数的初始化列表

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>

using namespace std;

class Test
{
public:
    Test()
    {
        cout << "test()..." << endl;
        m_x = 0;
        m_y = 0;
    }
    Test(int x, int y)
    {
        cout << "Test(int x, int y)..." << endl;

        m_x = x;
        m_y = y;
    }
    Test(const Test & another)
    {
        cout << "Test(const Test &)..." << endl;
        m_x = another.m_x;
        m_y = another.m_y;
    }

    void operator=(const Test &another)
    {
        cout << "operatoer = (const Test &)" << endl;
        m_x = another.m_x;
        m_y = another.m_y;
    }

    void printT() {
        cout << "x = " << m_x << ", m_y = " << m_y << endl;
    }

    ~Test() {
        cout << "~Test()..." << endl;
    }
private:
    int m_x;
    int m_y;
};


//析构函数调用的顺序, 跟构造相反, 谁先构造的,谁后析构。
//场景1
void test1()
{
    Test t1(10, 20);
    Test t2(t1);//Test t2 = t1;
}

//场景2
void test2()
{
    Test t1(10, 20);
    Test t2;

    t2 = t1;//=操作符
}


void func(Test t)//Test t = t1; //Test t 的拷贝构造函数
{
    cout << "func begin..." << endl;
    t.printT();
    cout << "func end..." << endl;
}

//场景3
void test3()
{
    cout << "test3 begin..." << endl;
    Test t1(10, 20);

    func(t1);

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


//场景4
Test func2()
{
    cout << "func2 begin..." << endl;
    Test temp(10, 20);
    temp.printT();

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

    return temp;
}//匿名的对象 = temp  匿名对象.拷贝构造(temp)

void test4()
{
    cout << "test4 being.. " << endl;
    func2();// 返回一个匿名对象。 当一个函数返回一个匿名对象的时候,函数外部没有任何
            //变量去接收它, 这个匿名对象将不会再被使用,(找不到), 编译会直接将个这个匿名对象
            //回收掉,而不是等待整改函数执行完毕再回收.
    //匿名对象就被回收。
    
    cout << "test4 end" << endl;
}

void test5()
{
    cout << "test 5begin.. " << endl;
    Test t1 = func2(); //会不会触发t1拷贝构造来   t1.拷贝(匿名)?
                        //并不会触发t1拷贝,而是 将匿名对象转正 t1,
                        //把这个匿名对象 起了名字就叫t1.

    cout << "test 5 end.." << endl;
}

//场景6
void test6()
{
    cout << "test6 begin..." << endl;
    Test t1;//t1已经被初始化了。

    t1 = func2(); //t1已经被初始化了,所以func2返回的匿名对象不会再次转正,而依然是匿名对象。
                    //所以t1会调用等号操作符,t1.operator=(匿名对象), 然后编译器会立刻回收掉匿名对象

    t1.printT();

    cout << "test6 end.." << endl;
}


int main(void)
{
    //test1();
    //test2();
    //test3();
    //test4();
    //test5();
    test6();

    return 0;
}

原文链接:https://www.cnblogs.com/ygjzs/p/12076497.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:C++ lambda expression

下一篇:c++-构造函数练习和delete,new