15-19(重载成员函数、构造函数、复制构造函数、类型转换构造函数、析构函数)

xiaoxiao2021-02-28  12

一、内联成员函数与重载成员函数

内联

class B { inline void func1();//第一种inline+成员函数 void func2() { //第二种,整个函数体在类定义内部,默认内联 } }; void B::func1(){}//第一种方式,别忘记类外定义

重载成员函数

#include <iostream> using namespace std; class location { private: int x, y; public: void init(int x = 0, int y = 0); void valueX(int val){ x = val; }//重载成员函数,第一个给x赋值 int valueX(){ return x; }//第二个返回x }; void location::init(int X, int Y)//定义init { x = X; y = Y; } int main() { location A;//声明对象A,类为location A.init(5)//缺省值,x=5;y默认0 A.valueX(5);//有参数,调用第一个valuex(int val) cout << A.valueX();//没有参数,调用第二个valuex() return 0; }

注意:使用缺省参数要注意避免函数重载时二义性

#include <iostream> using namespace std; class location { private: int x, y; public: void init(int x = 0, int y = 0); void valueX(int val=0){ x = val; }//重载成员函数,第一个给x赋值 int valueX(){ return x; }//第二个返回x }; location A; A.valueX();//错误,编译器无法判断调用哪个valueX void valueX(int val=0){ x = val; }//重载成员函数,第一个给x赋值 int valueX(){ return x; }//第二个返回x }; location A; A.valueX();//错误,编译器无法判断调用哪个valueX

二、构造函数

名字与类名相同,可以有参数,不能有返回值(void也不行)

作用:对对象进行初始化,给成员变量赋值。默认的构造函数无参数,不进行任何操作。

对象生成时构造函数自动被调用,一旦对象生成,再也不能在其上执行构造函数。

 

//默认的构造函数 class complex { private: double real, imag; pbulic: void set(double r, double i); };//编译器自动生成默认构造函数 complex c1;//生成对象时,默认构造函数被调用; complex *pc = new complex;//默认构造函数被调用

 

class complex { private: double real, imag; pbulic: complex(double r, double i=0); }; complex::complex(double r, double i) { real = r; imag = i; } complex c1;//error,缺少构造函数的参数,没法对对象c1初始化 complex c1(2)//OK,第二个参数可以缺省,r=2,i=0

一个类有多个构造函数,形成重载的关系

class complex { private: double real, imag; public: void set(double r, double i); complex(double r, double i);//声明构造函数 complex(double r); complex(complex c1, complex c2); }; //定义构造函数 complex::complex(double r, double i) { real = r; imag = i; } complex::complex(double r) { real = r; imag = 0; } complex::complex(complex c1, complex c2); { real = c1.real + c2.real; imag = c1.imag + c2.imag; } complex c1(2), c2(1, 0), c3(c1,c2) //c1(2)选择第二个,整型可以自动转成double

构造函数在数组中的使用

class complex { int x; public: csample()//无参数的构造函数 { cout << "constructor 1 called" << endl; } csample(int n)//有参数的构造函数 { x = n; cout << "constructor 2 called" << endl; } }; int main() csample array1[2];//使用无参构造函数 cout << "step1" << endl; /* 输出 constructor 1 called constructor 1 called step1 */ csample array2[2] = { 4, 5 }; cout << "steo2" << endl; /* 输出 constructor 2 called constructor 2 called step2 */ csample array3[2] = { 3 };//第一个有参,第二个无参 cout << "step3" << endl; /* 输出 constructor 2 called constructor 1 called step3 */ csample *array4 = new csample[2] delete[]array4;//new的要在结束之前收回 return 0

 

 

注意:(1)每建立一个对象,就调用一次构造函数;

(2)构造函数没有返回值,因此也没有类型,作用只是对对象进行初始化;

(3)构造函数不需要被用户调用,也不能被用户调用。

三、复制构造函数(copy constructor)

定义:只有一个参数,即对同类对象的引用。X::X ( X &)或者 X::X( const X &);

//如果定义自己的复制构造函数,默认的复制构造函数将不存在 class complex { public: double real, imag; complex(){} complex(const complex &c)//定义复制构造函数 { real = c.real;//被初始化对象的实部和参数的实部一样 imag = c.imag; cout << "copy constructor called";//复制构造函数内部不一定只有复制,可以自己加 } }; complex c1; complex c2(c1);

复制构造函数起作用三种情况

//一个对象去初始化同类的另一个对象 complex c2(c1); complex c2 = c1;//初始化语句,非赋值语句 //某函数一个参数是类A的对象,那么这个函数被调用时,类A的复制构造函数将被调用 class A { public: A(){}; A(A &a) { cout << "copy constructor called" << endl;//没有做复制的工作 } }; void func(A a1){}//形参a1是类A的对象,形参a1是由复制构造函数初始化的 int main() { A a2; func(a2); return 0; } //函数的返回值是类A的对象,函数返回时,A的复制构造函数被调用 class A { public: int v; A(int n){ v = n; }; A(const A&a) { v = a.v; cout << "copy constructor called" << endl; } }; A.func()//func函数返回值类型为A { A b(4); return b; } int main() { cout << func().v << endl;//要先生成这个对象, return 0; }

四、类型转换构造函数

特点:只有一个参数;不是复制构造函数;建立一个临时变量/临时对象。

class complex { public: double real, imag; complex(int i)//类型转换构造函数,只有一个参数 { cout << "int constructor called" << endl; real = i; imag = 0; } complex(double r,double i)//构造函数,初始化实部虚部 { real = r;imag=i } }; int main() { complex c1(7, 8);//第二个简单的构造函数 complex c2 = 12;//对c2进行初始化(不是赋值) c1 = 9;//赋值语句,=两边类型不同,9被自动转换为一个临时complex对象,调用了类型转换构造函数 cout << c1.real << "." << c1.imag << endl; return 0; } /* 输出 int constructor called int constructor called 9 0 */

 

五、析构函数(destructor)

特点:名字与类名相同,没有参数和返回值,一个类最多只有一个析构函数

在对象消亡时自动被调用,释放分配的空间

class string { private: char *p; public: string() { p = new char[10]; } ~string();//声明析构函数 }; string::~string()//定义析构函数 { delete[]p; }

 

对象数组生命周期结束时,对象数组 每个元素的析构函数都会被调用。 delete运算导致析构函数调用 ctest *ptest; ptest = new ctest;//构造函数调用 delete ptest;//析构函数调用 ptest = new ctest[3];//构造函数调用三次 delete [] ptest;//析构函数调用三次

 

总结: class demo { int id;//默认的private public: demo(int i)//构造函数 { id = i; cout << "id=" << id << "constructed" << endl; } ~demo()//析构函数 { cout << "id=" << id << "destructed" << endl; } }; demo d1(1);//全局d1变量 /* 输出id=1 constructed */ void func() { static demo d2(2);//静态的最终才被消亡 demo d3(3); cout << "func" << endl; /* 输出 id=2 constructed; id=3 constructed临时变量需要被析构掉 func id=3 destructed */ } int main() { demo d4(4);//局部d4对象 /* 输出id=4 constructed */ d4 = 6;//d4.id=6;赋值语句,右边变量通过类型转换构造函数,生成临时变量 /* 输出 id=6 constructed; id=6 destructed;临时变量需要被析构掉 */ cout << "main" << endl; {demo d5(5); }//作用域 /* 输出 id=5 constructed; id=5 destructed;临时变量需要被析构掉 */ func(); cout << "main ends" << endl; return 0; } /* 输出 id=6 destructed id=2 destructed id=1 destructed 先构造的最后消亡 */

 

转载请注明原文地址: https://www.6miu.com/read-2150211.html

最新回复(0)