C++基础 对象的管理——单个对象的管理
1. 为什么要有构造函数和析构函数
面向对象的思想是从生活中来,手机、车出厂时,是一样的。
这些对象都是被初始化后才上市的,初始化是对象普遍存在的一个状态。
普通方案:
对每个类提供一个 init 函数,对象创建后立即调用 init 函数进行初始化。
这种方案麻烦,并且不易用于对象数组。
所以需要构造函数,对应需要析构函数。
2. 对象的构造
(1)构造函数的定义
c++类可以定义与类名相同的特殊成员函数,此函数为构造函数。
构造函数在定时可以有参数,但无任何返回类型声明。
(2)构造函数的调用
自动调用:对象定义时,c++编译器会自动调用构造函数。
手动调用:程序员可手动调用。
(3)构造函数的分类
//有参数构造函数的三种调用方法 class test { private: int a; int b; public: //无参数构造函数 test() { ; } //带参数的构造函数 test(int a, int b) { ; } //赋值构造函数 test(const test &obj) { ; } public: void init(int _a, int _b) { a = _a; b = _b; } };
(4)构造函数的调用
(a)无参构造函数
test t1,t2;
(b)有参构造函数
//有参数构造函数的三种调用方法 class test5 { private: int a; public: //带参数的构造函数 test5(int a) { printf("\na:%d", a); } test5(int a, int b) { printf("\na:%d b:%d", a, b); } public: }; int main55() { test5 t1(10); //c++编译器默认调用有参构造函数 括号法 test5 t2 = (20, 10); //c++编译器默认调用有参构造函数 等号法 test5 t3 = test5(30); //程序员手工调用构造函数 产生了一个对象 直接调用构造构造函数法 system("pause"); return 0; }
(c)拷贝构造
【1】在函数体内的拷贝构造
注意与拷贝函数区分。
#include "iostream" using namespace std; class aa { public: aa() //无参构造函数 默认构造函数 { cout<<"我是无参构造函数,自动被调用了"<<endl; } aa(int _a) //无参构造函数 默认构造函数 { a = _a; cout << "我是有参构造函数" << endl; } aa(const aa &obj2) { cout<<"我也是拷贝构造函数,我是通过另外一个对象obj2,来初始化我自己"<<endl; a = obj2.a + 10; } ~aa() { cout<<"我是析构函数,自动被调用了"<<endl; } void geta() { printf("a:%d \n", a); } protected: private: int a; }; //单独搭建一个舞台 void objplay01() { aa a1; //变量定义 //赋值构造函数的第一个应用场景 //用对象1 初始化 对象2 aa a2 = a1; //定义变量并初始化 //初始化法 a2 = a1; //用a1来=号给a2 编译器给我们提供的浅copy } int main() { objplay01(); system("pause"); }
【2】函数传参时的拷贝构造
#include "iostream" using namespace std; class location { public: location( int xx = 0 , int yy = 0 ) { x = xx ; y = yy ; cout << "有参构造\n" ; } location( const location & p ) //复制构造函数 { x = p.x ; y = p.y ; cout << "拷贝构造" << endl ; } ~location() { cout << x << "," << y << " 析构" << endl ; } int getx () { return x ; } int gety () { return y ; } private : int x , y ; } ; //alt + f8 排版 void f ( location p ) { cout << "funtion:" << p.getx() << "," << p.gety() << endl ; } void mainobjplay() { location a ( 1, 2 ) ; //形参是一个元素,函数调用,会执行实参变量初始化形参变量 f ( a ) ; } void main() { mainobjplay(); system("pause"); }
【3】函数返回与拷贝构造
注意匿名对象的拷贝构造,和析构。
//第四个应用场景 #include "iostream" using namespace std; class location { public: location( int xx = 0 , int yy = 0 ) { x = xx ; y = yy ; cout << "构造函数\n" ; } location( const location & p ) //复制构造函数 { x = p.x ; y = p.y ; cout << "拷贝构造" << endl ; } ~location() { cout << x << "," << y << " 析构函数" << endl ; } int getx () { return x ; } int gety () { return y ; } private : int x , y ; } ; //alt + f8 排版 void f ( location p ) { cout << "funtion:" << p.getx() << "," << p.gety() << endl ; } location g() { location a(1, 2); return a; } //对象初始化操作 和 =等号操作 是两个不同的概念 //匿名对象的去和留,关键看,返回时如何接 void mainobjplay() { //若返回的匿名对象,赋值给另外一个同类型的对象,那么匿名对象会被析构 location b; b = g(); //用匿名对象 赋值 给b对象,然后匿名对象析构 //若返回的匿名对象,来初始化另外一个同类型的对象,那么匿名对象会直接转成新的对象 //location b = g(); } void main() { mainobjplay(); system("pause"); }
第二种情况:
定义一个新符号去接匿名对象,那么匿名对象会直接转换成新符号对象。
//第四个应用场景 #include "iostream" using namespace std; class location { public: location( int xx = 0 , int yy = 0 ) { x = xx ; y = yy ; cout << "构造函数\n" ; } location( const location & p ) //复制构造函数 { x = p.x ; y = p.y ; cout << "拷贝构造" << endl ; } ~location() { cout << x << "," << y << " 析构函数" << endl ; } int getx () { return x ; } int gety () { return y ; } private : int x , y ; } ; //alt + f8 排版 void f ( location p ) { cout << "funtion:" << p.getx() << "," << p.gety() << endl ; } location g() { location a(1, 2); return a; } //对象初始化操作 和 =等号操作 是两个不同的概念 //匿名对象的去和留,关键看,返回时如何接 void mainobjplay() { //若返回的匿名对象,赋值给另外一个同类型的对象,那么匿名对象会被析构 // location b; //b = g(); //用匿名对象 赋值 给b对象,然后匿名对象析构 //若返回的匿名对象,来初始化另外一个同类型的对象,那么匿名对象会直接转成新的对象 location b = g(); } void main() { mainobjplay(); system("pause"); }
(5)默认构造函数
两个特殊的构造函数:
1)默认无参构造函数
当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空。
2)默认拷贝构造函数
当类中没有定义拷贝构造函数时,编译器默认提供一个默认拷贝构造函数,进行浅拷贝。
(6)构造函数调用规则
1)当类中没有定义任何一个构造函数时,c++编译器提供默认无参构造函数和默认拷贝构造函数。
2)当类中定义了拷贝构造函数时,c++编译器不会提供拷贝构造函数。
3)当类中定义了任意非拷贝构造函数,c++编译器不会提供默认无参构造函数。
3. 对象的析构
(1)析构函数的定义
语法:~classname()
作用:清理对象
(2)析构函数的调用
对象析构时,c++编译器自动调用。