C++ 类创建相关(构造函数、拷贝构造、赋值)

类对象构造

1、分配内存空间
2、调用构造函数 初始化内存空间

默认函数

C++的空类,编译器会加入哪些默认的成员函数

  1. 默认构造函数和拷贝构造函数
  2. 析构函数
  3. 赋值函数(重载赋值运算符=)

构造函数 拷贝构造函数

1. 构造函数不能为虚函数

To construct an object, a constructor needs the exact type of the object it is to create. Consequently, a constructor cannot be virtual. Furthermore, a constructor is not quite an ordinary function, In particular, it interacts with memory management in ways ordinary member functions don’t. Consequently, you cannot have a ponter to a constructor.

— From 《The C++ Progamming Language》15.6.2
C++对象构建过程有两步:首先,分配一块内存;其次,调用构造函数。如果构造函数是虚函数,就需要通过vtable 来调用,但是vtable是调用构造函数初始化后生成的。

2、如何在一个类的构造函数汇中调用另一个构造函数
构造函数是不允许嵌套调用的,但可以调用不同的重载形式。比如下面代码:(注意这是一道面试题目)

struct CLS
{
    int m_i;
    CLS( int i ) : m_i(i){
        printf("ee\n");
    }
    CLS(){CLS(0);
        printf("dd\n");
    }
};
int main()
{
    CLS obj;
    std::cout << obj.m_i << std::endl;
    getchar();
    return 0;
}

这里写图片描述
CLS(0);”的语句表示创建一个临时的CLS对象,并把该对象的成员m_i初始化为0。当前对象的值并没有初始化。
如果需要实现构造函数类调用另一个构造函数,需要借助于placement new运算符。代码如下:

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

如果你对placement new不了解,建议看看c++ primer或者TCPL。
在c++11中可以直接通过委托或继承构造函数的形式实现上面功能。

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

3、.拷贝构造函数
拷贝构造函数是C++独有的,它是一种特殊的构造函数,用基于同一类的一个对象构造和初始化另一个对象。
1. 浅拷贝
系统默认创建,即将被拷贝对象的数据成员的值一一赋值给新创建的对象,若该类的数据成员中有指针成员,则会使得新的对象的指针所指向的地址与被拷贝对象的指针所指向的地址相同,delete该指针时则会导致两次重复delete而出错。

2、在《inside the c++ object model》一书中谈到copy constructor的构造操作,有三种情况下,会以一个object的内容作为另一个object的初值:

第一种情况: XX aa = a;  
第二种情况: XX aa(a);  
第三种情况: extern fun(XX aa); fun(a)函数调用  
第四种情况: XX fun(){...}; XX a = fun();函数返回值的时候  

4、初始化成员列表
《C++ Primer》中提到在以下三种情况下需要使用初始化成员列表:

情况一、需要初始化的数据成员是对象的情况(这里包含了继承情况下,通过显示调用父类的构造函数对父类数据成员进行初始化);

情况二、需要初始化const修饰的类成员或初始化引用成员数据;

情况三、子类初始化父类的私有成员;

情况一的说明:数据成员是对象,并且这个对象只有含参数的构造函数,没有无参数的构造函数;
如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成员它只有一个带参数的构造函数,而没有默认构造函数,这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,如果没有初始化列表,那么他将无法完成第一步,就会报错。

5、赋值
赋值运算的重载声明如下:

A& operator = (const A& other)

拷贝构造函数是一个对象初始化一块内存区域,这块内存就是新对象的内存区,而赋值函数是对于一个已经被初始化的对象来进行赋值操作。

<span style="font-size:14px;">class  A;  
A a;  
A b=a;   //调用拷贝构造函数(b不存在)  
A c(a) ;   //调用拷贝构造函数  

/****/  

class  A;  
A a;  
A b;     
b = a ;   //调用赋值函数(b存在)</span>  

总结:

对象不存在,且没用别的对象来初始化,就是调用了构造函数;
对象不存在,且用别的对象来初始化,就是拷贝构造函数
对象存在,用别的对象来给它赋值,就是赋值函数。

参考

虚函数
[1] 从一道题谈C++中构造函数调用构造函数 http://www.cnblogs.com/chio/archive/2007/10/20/931043.html

[2] c++ 一个构造函数 调用 另一个 构造函数 http://www.cnblogs.com/ayanmw/archive/2012/08/20/2647808.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值