c++ mooc 构造函数,复制构造函数,类型转换构造函数, 析构函数

构造函数:

是在对象已经具有空间以后做一些初始化的工作,不负责分配空间

是成员函数的一种,与类名相同,可以带参,无返回值,对对象做初始化

类默认有构造函数,无参无操作

有对象生成时一定调用构造函数

一个类可有多个构造函数

class Rectangle:
{
    private: 
        int w,h;
    public:
        Rectangle(int i, int j=0);
        Rectangle();
        Rectangle(Rectangle r1, Rectangle r2);
};

//三个构造函数
Rectangle::Rectangle(int i, int j=0){
        w = i;
        h = j;
}
Rectangle::Rectangle(){
        w = 0;
        h = 0;
}
Rectangle::Rectangle(Rectangle r1, Rectangle r2){
        w = r1.w + r2.w;
        h = r1.h + r2.h;
}


int main(){
    //第二个,第一个,第三个构造函数
    Rectangle r(),r1(1),r2(r,r1);
    //Rectangle r;  也用第二个
}

构造函数在数组的使用

指针不会引发对象的生成:

扫描二维码关注公众号,回复: 11321506 查看本文章
Rectangle *r[3];  //不会调用任何构造函数,因为是一个指针数组
Rectangle *r[3]={new Rectangle(4), NULL, new Rectangle(1,2)} //只生成两个对象,new返回为指针

复制构造函数

形如  X::X( X& x) 或 X::X(const X& x) ,参数为同类对象的引用,无定义编译器默认生成,完成两个对象复制的功能

复制构造函数与无参构造函数区别:

      1. 无参构造函数也称默认构造函数,不一定存在(你不写任何构造函数编译器才会默认生成)

      2. 复制构造函数一定存在(要么你写要么编译器帮你写),复制构造函数只有一个

class Complex:{
    private:
        double img,re;
};

int main(){
Complex c1;
Complex c2(c1);  //调用缺省的默认的复制构造函数,c2与c1一样
}

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

//1.
Complex c1;

//2.初始化同类的另一个对象
Complex c2(c1);   //或Complex c2=c1;

//某函数Func()的参数是类A的对象,则Func调用时,类A的复制构造函数将被调用
class A:
{    
    public:
        A(){};
        A(A & a){cout<<"copy construct"<<endl};
};

void Func(A a1){}

int main(){
    A a2;
    Func(a2);     //此时a1对象的初始化调用复制构造函数,但我们的复制构造函数不是拷贝,所以a1可
                  //能不是a2的拷贝  
    return 0;
}

//3.若函数Func的返回值为A的对象时,Func返回时A的复制构造函数被调用
class A:
{    
    public:
        int v;
        A(int n){v=n;};
        A(const A & a){
        v = a.v
        cout<<"copy construct"<<endl
        };
};
A Func(){
    A a1(3);
    return a1;
}
int main(){
    cout<<Func().v<<endl;  //3
    
    return 0;
}

对象间的赋值不等于复制构造函数被调用比如:

Complex c1;
c1=c2;

为了减少函数调用时,复制构造函数调用所产生的时间开销,可以用常量引用参数

void Func(const A & a ){}

引用的参数与实参是一回事,不会生成对象,若想让函数内部操作改变形参不改变实参,加上const

类型转换构造函数

为了实现类型转换

只有一个参数且不是复制构造函数

需要时编译器自动调用,生成一个无名临时对象

class Complex:
{
    public:
        double a,b;
        Complex(double i, double j){a=i;b=j;}
        Complex(int i){a=i; b=0;}  //double to int
};

int main(){
    Complex c1(7,8);  //7.0,8.0
    Complex c2=12;    //a=12,b=0
    c1=9;             //编译器将9自动转换为一个无名临时对象其a=9,b=0,再将这个临时对象赋给c1
    return 0;
}

析构函数(destructor)

在对象消亡时被调用(可为释放空间等),一个类最多一个

若不写编译器会自动生成(什么都不做)

函数名为:‘~’ + ‘className’

无参无返回值

在对象的空间被回收前的操作

class String:
{
       private:
            char *p;
       public:
            String(){
                p = new char[10];
            }
            ~ String();
};

String::~ String(){
    delete []p;
}

对象数组生命周期结束时,其中的每个元素的析构函数都会被调用

消亡的几种情况:

//1. main函数结束时
class A:
{
    public:
        int a;
    ~ A(){cout<< "destructor" <<endl;}        
};

int main(){
A a[2];
cout<< "end main" <<endl;

return 0;
}
//输出结果为:
//end main
//destructor
//destructor


//2.new出的对象,delete时消亡,不delete不消亡
A *a;
a = new A;
delete a;   //析构函数调用

A a1[3];
delete [] a;  //析构函数调用三次


//3. 对象作为函数返回值,返回后调用析构函数
class A:
{
    public:
        int a;
    ~ A(){cout<< "destructor" <<endl;}        
};

A func(A sa)              //调用默认复制构造函数初始化形参sa
{
    return sa;            //返回形参sa后析构函数被调用
}

int main(){
    A a;
    a = func(a);          //func(a)生成一个返回值对象(临时对象),用复制构造函数初始化,其值赋
                          //值给a,执行完这条语句后,临时对象消亡,调用析构函数
    cout<< "end main" <<endl; 

    return 0;             //main结束后,全局对象a消亡,调用析构函数
}
//输出结果为:
//destructor
//destructor
//end main
//destructor

相关实例

析构函数和构造函数被调用实例:

class A:
{
    public:
        int a;
        A(int i){     //构造函数,也可算类型转换构造函数
            a=i;
            cout << "a" << a << " construct" << endl;
        };
        ~ A(){
            cout << "a"<< a << " destruct" << endl;
        }        
};

A a1(1);                               //step1:全局对象在main之前初始化,在整个程序结束后消亡

void func(){                           
    static A a2(2);                    //step8:静态局部变量初始化,在全部程序结束后消亡
    A a3(3);                           //step9:局部变量a3初始化,在func结束后消亡
    cout << "func end" << endl;
}

int main(){                   
    A a4(4);                           //step2:初始化a4,在main结束后消亡
    a4 = 6;                            //step3:类型转换构造函数生成值为6的临时对象
                                       //step4:临时对象赋值语句结束后消亡
    cout << "main" << endl;            //step5
    {A a5(5);}                         //step6:局部对象a5生成
                                       //step7:包含a5的最内层大括号结束后a5消亡
    func();
    cout << "end main" << endl;
}

//输出结果
// a1 construct
// a2 construct
// a4 construct
// a6 construct
// a6 destruct
// main
// a5 construct
// a5 destruct
// a2 construct
// a3 construct
// func end
// a3 destruct
// end main
// a6 destruct       //先消亡main内的
// a2 destruct       //因为a1比a2先初始化,后消亡
// a1 destruct

构造函数在不同编译器中表现

dev c++呼吁优化目的没有生成返回值临时对象,一般情况下没什么问题

猜你喜欢

转载自blog.csdn.net/scarletteshu/article/details/103430087