关于构造函数的其他例子

讨论2: 再谈构造函数

1. new创建对象数组,调用什么样的构造函数?

class Point

{

public:

    Point(double xx=0, double yy=0):x(xx),y(yy)

    {

        cout << "调用Point构造函数" << endl;

    }

private:

    double x;

    double y;

};

int main()

{

    Point *p1= new Point[4];

    return 0;

}

输出结果:

调用Point构造函数

调用Point构造函数

调用Point构造函数

调用Point构造函数

 

结论:new创建对象数组,如上所示,Point类需要提供默认构造函数(构造函数没有参数,或者构造函数带默认参数,或者不提供构造函数用系统默认的构造函数)

 

2. 构造函数可以是私有的吗?

class Point

{

public:

    Point(double xx, double yy):x(xx),y(yy)

    {

        cout << "调用Point构造函数" << endl;

    }

private:

    Point(){}  //构造函数私有

    double x;

    double y;

};

int main()

{

    Point p1; //errorCalling a private constructor of class 'Point'

    Point p2(3,4);

    return 0;

    

}

结论:可以定义私有构造函数,例如希望定义对象时用户指定初始值。

 

3. 对象可以自己调用构造函数吗?

class Point

{

public:

    Point(double xx=0, double yy=0):x(xx),y(yy)

    {

        cout << "调用Point构造函数" << endl;

    }

private:

    double x;

    double y;

};

int main()

{

    Point p1;

    p1.Point(5,5);  //errorCannot refer to type member 'Point' in 'Point' with '.'

    return 0;

}

结论:对象不能自己调用构造函数

 

4. 关于函数参数是传值还是传引用的问题

下面的例子Distance求两点间距离,主函数定义两个点,然后用这两个点初始化一个Distance对象,执行Distance构造函数,求出两点间距离

class Point

{

public:

    Point(double xx=0, double yy=0):x(xx),y(yy)

    {

        cout << "调用Point构造函数" << endl;

    }

    Point(const Point & p)

    {

        cout << "调用Point拷贝构造函数" << endl;

        x = p.x;

        y = p.y;

    }

    double GetX( ) const

    {

        return x;

    }

    double GetY( ) const

    {

        return y;

    }

private:

    

    double x;

    double y;

};

 

class Distance

{

public:

               //注意这里参数传递是引用    

Distance(const Point& a, const Point& b):p1(a), p2(b)

    {

        cout << "调用Distance构造函数" << endl;

        double x = p1.GetX( ) + p2.GetX( );

        double y = p1.GetY( ) + p2.GetY( );

        dist = sqrt(x*x + y*y);

    }

    double GetDist( )

    {

        return dist;

    }

private:

    Point p1, p2;

    double dist;

};

 

int main( )

{

    Point p1(1.1, 2.2), p2(3.3, 4.4);

    Distance d(p1, p2);

    cout << "the distance is " << endl;

    cout << d.GetDist( ) << endl;

    return 0;

}

输出结果:

调用Point构造函数

调用Point构造函数

调用Point拷贝构造函数

调用Point拷贝构造函数

调用Distance构造函数

the distance is

7.93221

 

结果分析:主函数第一个语句输出前两行内容调用Point构造函数,主函数第二个语句Distance d(p1, p2);输出接下来的三行内容,当执行Distance构造函数参数初始化p1(a), p2(b)时共调用Point拷贝构造函数两次。

 

进一步解释参数传递是引用传递,主函数执行这条语句Distance d(p1, p2);调用构造函数,参数传递,即const Point &a=p1, &b=p2; 这就是给已有对象(主函数的p1p2)起了别名ab,没有新的点对象产生。因为没有产生新对象,所以系统不会调用(拷贝)构造函数。即参数传递是引用时不调用拷贝构造函数!

 

如果将Distance构造函数修改如下,上面的代码其它地方不变,输出结果为:

            //注意这里,参数传递是值传递

Distance(const Point a, const Point b):p1(a), p2(b)

    {

        cout << "调用Distance构造函数" << endl;

        double x = p1.GetX( ) + p2.GetX( );

        double y = p1.GetY( ) + p2.GetY( );

        dist = sqrt(x*x + y*y);

    }

 

输出结果:

调用Point构造函数

调用Point构造函数

调用Point拷贝构造函数

调用Point拷贝构造函数

调用Point拷贝构造函数

调用Point拷贝构造函数

调用Distance构造函数

the distance is

7.93221

 

解释参数传递是值传递的情况,主函数执行这条语句Distance d(p1, p2);调用构造函数,参数传递,即const Point a=p1, b=p2; 这就是用已有对象初始化新对象,系统自动调用拷贝构造函数。

对比输出结果:多了两行输出,多执行了两次调用Point拷贝构造函数

 

结论:参数传递如果是值传递,会调用拷贝构造函数,产生新对象;参数传递如果是引用传递,只是给实参起了别名,没有定义新对象,没有调用拷贝构造函数。引用方式传参显然更好,推荐大家参数传递这样写const Point& a也就是当传值和传引用都可以时首选传引用,为了避免对实参的修改,请加上const

 

5. 关于函数类型是类对象还是对象引用的问题

含义与函数参数是传参还是传引用的问题类似,函数类型是类类型,表示函数执行结束返回调用处时系统自动调用拷贝构造函数(你如果没写,系统会有默认的拷贝构造函数),产生新的无名临时对象,如果函数类型是类引用,表示没有新对象产生。

原文地址:https://www.cnblogs.com/zhaoyiyao/p/12703886.html