• 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;
    }
    
  • 相关阅读:
    突然想到一个问题:有关 cqrs 分离
    Oracle 12C 数据库安装与配置
    Android 绑定服务的作用 (参考,不确定他说的是不是对的)
    SSM框架整合(一)
    常见数据库优化方案(九)
    大量文件存储
    MyBatis 参数传递小知识(划重点)|划掉 MyBatis 常见小debug
    MyBatis 自动代码生成器
    常见数据库优化方案(八)
    常用数据库优化方案(五)
  • 原文地址:https://www.cnblogs.com/ygjzs/p/12076497.html
Copyright © 2020-2023  润新知