注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

和申的个人主页

专注于java开发,1985wanggang

 
 
 

日志

 
 

从一道题谈C++中构造函数调用构造函数  

2014-03-23 22:44:12|  分类: C/C++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
背景说明:
练习c++的时候惊喜的发现
构造函数调用构造函数的时候,并不能初始化相应的变量
Rectangle::Rectangle(){
    Rectangle(22,33);
}
比如这么在java中类似的应该会调用构造函数,这里面
这样调用后,对应的值依旧是未初始化的值。
从一道题谈C++中构造函数调用构造函数 - 和申 - 和申的个人主页

具体代码如下:
#include <iostream>
class Rectangle{


public:
    unsigned width, height;
    Rectangle();
    Rectangle(unsigned x, unsigned y );
    void setSize(unsigned x, unsigned y);
    unsigned area();
    bool isSquare();
};
int main(){
    Rectangle rectangle;

    std::cout << "width :" << rectangle.width

            << " height: " << rectangle.height << "\n";



    rectangle.setSize(1,2);

    std::cout << "width :" << rectangle.width

            << " height: " << rectangle.height << "\n";

    return 0;

}

void Rectangle::setSize(unsigned x, unsigned y){

    this->width = x;

    this->height = y;

}
Rectangle::Rectangle(){
    Rectangle(22,33);   // new (this)Rectangle(22,33);
}
Rectangle::Rectangle(unsigned x, unsigned y){
    this->width = x;
    this->height = y;
}
从一道题谈C++中构造函数调用构造函数 - 和申 - 和申的个人主页
 本来期望的结果应该是函数调用  Rectangle(22,33);构造函数将自身初始化为22,33
结果出来个内存脏数据,
赶紧查询下往上 ,c++构造函数调用构造函数的问题 ,这个地方和java不同,不能类似的构造函数调用自身
this(xx,xx),super(xx,xx)

c++解决办法:
1. new (this)Rectangle(22,33);采用这种方式,见下文。
2. 采用c++常用的重载函数的方式,直接在声明函数的时候,赋值默认值避免此类情况发生。

具体文章如下:
没有查具体这种写法是否会分配新内存,不过,确实会给对象初始化。
================================================================================
题目如下:问下列代码的打印结果为0吗?
#include <stdlib.h>
#include 
<iostream>
using namespace std;

struct CLS
{
    
int m_i;
    CLS( 
int i ) : m_i(i){}
    CLS()
    {
        CLS(
0);
    }
};
int main()
{
    CLS obj;
    cout 
<< obj.m_i << endl;

    system(
"PAUSE");
    
return 0;
}
打印结果是不定的,不一定为0

代码奇怪的地方在于构造函数中调用了自己的另一个构造函数

我们知道,当定义一个对象时,会按顺序做2件事情:
1)分配好内存(非静态数据成员是未初始化的)
2)调用构造函数(构造函数的本意就是初始化非静态数据成员)

显然上面代码中,CLS obj;这里已经为obj分配了内存,然后调用默认构造函数,但是默认构造函数还未执行完,却调用了另一个构造函数,这样相当于产生了一个匿名的临时CLS对象,它调用CLS(int)构造函数,将这个匿名临时对象自己的数据成员m_i初始化为0;但是obj的数据成员并没有得到初始化。于是obj的m_i是未初始化的,因此其值也是不确定的

从这里,我们归纳如下:
1)在c++里,由于构造函数允许有默认参数,使得这种构造函数调用构造函数来重用代码的需求大为减少
2)如果仅仅为了一个构造函数重用另一个构造函数的代码,那么完全可以把构造函数中的公共部分抽取出来定义一个成员函数(推荐为private),然后在每个需要这个代码的构造函数中调用该函数即可
3)偶尔我们还是希望在类的构造函数里调用另一个构造函数,可以按下面方式做:
在构造函数里调用另一个构造函数的关键是让第二个构造函数在第一次分配好的内存上执行,而不是分配新的内存,这个可以用标准库的placement new做到:

    先看看标准库中placement new的定义

inline void *__cdecl operator new(size_t, void *_P)
{
    
return (_P); 

可见没有分配新的内存。

正确的方式:

struct CLS
{
    
int m_i;
    CLS( 
int i ) : m_i(i){}
    CLS()
    {
        
new (this)CLS(0);
    }
};

 


另: 若构造函数调用自身,则会出现无限递归调用,是不允许的


摘自:http://www.cnblogs.com/chio/archive/2007/10/20/931043.html

  评论这张
 
阅读(464)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016