c++-构造函数
程序员文章站
2022-06-11 15:56:02
构造函数 + 构造和析构概念语法 + 构造函数的分类 + 有参构造函数3种调用方法 + 拷贝构造函数4种调用时机 场景1和2:A a(b); A a = b; 场景3:形参是一个元素,实参传递给形参 场景4:函数返回值返回一个元素,匿名对象 匿名对象的去和留 对象的初始化 和 对象的=操作 是两个不 ......
构造函数
- 构造和析构概念语法
- 构造函数的分类
- 有参构造函数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; }