构造,析构,复制构造,重载=,和自动创建无名变量的问题(习题)

来源:互联网 发布:工业电脑如何编程 编辑:程序博客网 时间:2024/05/24 07:25

关于构造,析构,复制构造,=,和自动创建无名变量

总结:

1.在新定义对象时,=调用复制构造函数,而对已有对象,=是运算符=

2.在计算时,如果类型不符,系统强制类型转换,调用最接近的构造函数,即  无名对象(a)   ,在完成此运算符对应的计算后,该无名变量就被析构掉


例1:

#include<iostream>using namespace std;class A{    float x,y;public:    A(){ x=0; y =0; cout<<"调用无参构造函数\n";}    A(float a){ x=a ; y= 0; cout<<"调用一个参数的构造函数\n"; }    A(float a,float b){ x=a; y =b; cout<<"调用两个参数的构造函数\n";}    A(A &a){ x= a.x ; y = a.y; cout<<"调用复制构造函数\n";}    ~A(){cout<<"调用析构函数\n";}    //A & operator  = (A & a){ x=a.x; y =a.y; cout<<"调用了运算符=的重载\n";}    void Print (){ cout<<x<<'\t'<<y<<endl;}};void f(){    A a0;         //此处若用  A a0 = 2+3;   则会报错                  //因为对象定义时, = 采用的是复制构造函数,没有相一致的复制构造函数对应    a0 = 2+3;     //定义构造函数时, A a0(2,3); 也可以写成 A a0 = A(2,3);    a0.Print();}A a1(7.0,3.0);    //主函数前的对象,先调用两个参数的构造函数int main(){    f();          //  A a0 调用无参构造函数    //  2+3 = 5 一般计算    //  强制类型转换,临时对象(5)     生成临时对象,用数值5对其构造,调用一个参数的构造函数    //  利用"=",a0调用复制构造函数,复制临时对象(5)这个对象    //  Print()函数打印    //  第一个析构的是无名对象,第二个析构的是a0,注意无名变量析构时也会调用析构函数    A a2(a1);     //  利用构造函数的一般形式,对a2构造,复制对象为a1    //  第三个析构是对a2的析构,第四个析构是对全局对象a1的析构    return 0;}

结果:

调用两个参数的构造函数
调用无参构造函数
调用一个参数的构造函数
调用析构函数
5 0
调用析构函数
调用复制构造函数
调用析构函数
调用析构函数



例2:

#include<iostream>using namespace std;int MMMax=0;class A{    int x,y;    static int count;public:    A(int a = 0 ,int b = 0){        x = a  ; y = b ; MMMax = ++count;        cout<<"调用了两个参数的构造函数\n";    }    A(A &c){        x=c.x; y=c.y; MMMax = ++count;        cout<<"调用了复制构造函数\n";    }    ~A(){ count--; cout<<"调用了析构函数\n";}    int getnum(){ return count;}};int A::count = 0;int main(){    A a1,a2(10,20);                //  a1 两个默认值的构造函数   a2 带有两个参数的构造函数                                   //  count 作为静态变量,调用构造函数时+1,所以这里0+2=2    cout<<"count="<<a2.getnum()<<endl;    A a3=a1;                       //  利用复制构造函数,直接将a1的内容复制给a3,中间没有无名对象过程,复制的过程取决于复制构造函数                                   //  当对象新定义时,=调用复制构造函数    cout<<"count="<<a3.getnum()<<endl;    a1 = A(20,30);                 //  强制类型转换,用两个参数的构造函数构造无名对象                                   //  a1是已有的对象,所以利用运算符=,将无名对象复制给a1                                   //  无名对象调用析构函数析构,在结束复制过程后即析构                                   //  调用析构函数时会用count--,所以MMMax和count的值不一样    cout<<"count="<<a1.getnum()<<endl;    cout<<"MMMax="<<MMMax<<endl;    A a4=a2;                       //  当对象新定义时,=调用复制构造函数    a4 = a2;                       //  当对象是已有时,=调用运算符=的重载                                   //  析构函数的顺序分别是a4,a3,a2,a1    return 0;}

结果:

调用了两个参数的构造函数
调用了两个参数的构造函数
count=2
调用了复制构造函数
count=3
调用了两个参数的构造函数
调用了析构函数
count=3
MMMax=4
调用了复制构造函数
调用了析构函数
调用了析构函数
调用了析构函数
调用了析构函数


例3:

#include<iostream>using namespace std;char gid = 'A';class Number{private:    int i;    char id;public:    Number(int x=0){        i = x;        id =gid++;        cout<<"Constructor Number:"<<id<<i<<endl;    }    Number( const Number &x ){        i=x.i;        id =gid ++;        cout<<"Copy Number:"<<id<<i<<endl;    }    ~Number(){cout<<"Destructor Number:"<<id<<i<<endl;}    Number operator+(const Number &x);};Number Number::operator+(const Number &x) {    Number result(i+x.i);    return result;}int main(){    Number x(1),y;    //调用一个参数的构造函数构造x,调用默认值的构造函数构造y    y = x+2;          //数字2强制类型转换,生成临时对象,用一个参数的构造函数构造来转换,无名变量(2)                      //重载运算符+进行计算,用一个参数的构造函数构造新对象,并在运算结束后析构,重载运算符+中不涉及无名变量等问题                      //如果将运算符+重载的内容直接改成 i=x.i; return *this; 则显示结果中Construtor:D3这一句改成Copy Number:D3                      //运算符=进行y的浅拷贝    return 0;}


结果:

Constructor Number:A1
Constructor Number:B0
Constructor Number:C2
Constructor Number:D3
Destructor Number:D3
Destructor Number:C2
Destructor Number:D3
Destructor Number:A1




例4:

#include<iostream>#include <cmath>using namespace std;class point{    int x,y;public:    point(int xx=0,int yy=0){        x= xx; y =yy;        cout<<"point的构造函数被调用\n";    }    point (point &p){        x = p.x;        y = p.y;        cout<<"point的复制构造函数被调用\n";    }    int GetX(){ return  x;}    int GetY(){ return  y;}};class line{    point p1, p2;    double len;public:    line (point xp1,point xp2):p1(xp1),p2(xp2){        cout<<"line的构造函数被调用\n";        double x = double (p2.GetX()-p1.GetX());        double y = double (p2.GetY()-p1.GetY());        len = sqrt(x*x+y*y);               //在私有数据中被定义,所以类外(class,不是对象)对len进行运算时,要用成员函数调用    }    line (line &l);    double GetLen(){ return len;}};int main(){    point myp1(1,1),myp2(4,5);              //myp1 两个参数的构造函数  myp2两个参数的构造函数    line line0(myp1,myp2);                  //myp1 做实参传给line0的复制构造函数line 中的xp1时,xp1 通过复制构造函数得到myp1的值                                            //xp1 做实参传给p1的复制构造函数point中的参数p时,p通过复制构造函数得到xp1的值                                            //myp2 xp2 p2 的类似上述过程,所以这边一共调用了4次复制构造函数    cout<<"The length of the line0 is :";    cout<<line0.GetLen()<<endl;             //计算    return 0;}

结果:

point的构造函数被调用
point的构造函数被调用
point的复制构造函数被调用
point的复制构造函数被调用
point的复制构造函数被调用
point的复制构造函数被调用
line的构造函数被调用
The length of the line0 is :5



例5:

#include<iostream>using namespace std;class Number{    int i;public:    Number(int x=0){        i=x;        cout<<"Constructor Number:"<<i<<endl;    }    ~Number(){        cout<<"Destructor Number:"<<i<<endl;    }    Number operator +(const Number &x){        Number result;        cout<<"Add Number"<<endl;        result.i = i+x.i;        return result;    }};int main(){    Number x(1),y(2);      //构造函数x(1)和构造函数y(2)    y=x+y;                 //运算符+重载中默认值构造函数                           //析构运算符+中的对象                           //运算符=浅拷贝                           //析构y 和 x    return 0;}

结果:

Constructor Number:1
Constructor Number:2
Constructor Number:0
Add Number
Destructor Number:3
Destructor Number:3
Destructor Number:1



例6:构造函数的作用是初始化,构造初始化列表先于构造函数函数体执行。

#include <iostream>using namespace std;class data{    int x;public:    data(int x){        data::x=x;        cout<<"class data"<<endl;    }};class a{    data d1;public:    a(int x):d1(x){        cout<<"class a"<<endl;    }};class b:public a{    data d2;public:    b(int x):a(x),d2(x){        cout<<"class b"<<endl;    }};class c:public b{public:    c(int x):b(x){        cout<<"class c"<<endl;    }};int main(){    c obj(5);    return 0;}

结果:

class data
class a
class data
class b
class c


例7

#include <iostream>using namespace std;class Sample{    int x,y;public:    Sample(int a=1,int b=1){        x=1,y=b;        disp();    }    Sample(Sample &s){        x=s.x;        y=s.y;        cout<<"in copy construct"<<endl;    }    Sample &operator=(Sample &s){        x=s.x;        y=s.y;        cout<<"in operator = "<<endl;        return *this;    }    ~Sample(){        if(x==y){            cout<<"x==y"<<endl;        }else{            cout<<"x!=y"<<endl;        }    }    void disp(){        cout<<"x="<<x<<"y="<<y<<endl;    }    friend void ms(Sample s);};void ms(Sample s){    s.x=s.y;}int main(){    Sample s1(2,3);   //调用两个参数的构造函数    Sample s2 = s1;   //调用复制构造函数,利用s1构造s2    ms(s2);           //调用复制构造函数,利用s2构造无名对象,参加后续函数运算的是无名构造对象                      //完成ms函数后,无名构造对象的x和y同,但是s2的值不受改变                      //析构无名变量,析构s2,析构s1    return 0;}

结果:

x=1y=3
in copy construct
in copy construct
x==y
x!=y
x!=y


例8:

#include <iostream>using namespace std;class A{public:    virtual void print(){        cout<<"A::print"<<endl;    }};class B:public A{public:    void print(){        cout<<"B::print"<<endl;    }};class C:public B{public:    void print(){        cout<<"C::print"<<endl;    }};void print(A a){     //参数的类型是A  ,相对于int float 之类的    a.print();}int main(){    C c;    print(c);        //c是C类型的,和A类型不符合,所以往C的父类中找相对应的函数    return 0;}


结果:

A::print








阅读全文
0 0