c++对象创建

来源:互联网 发布:手机遥控ppt软件 编辑:程序博客网 时间:2024/06/05 03:05
栈上创建对象
在没有new创建对象时,也即栈上创建对象,没有参数的话,不要写括号。
如 A a();这种写法就是不对的,他会被理解为声明函数,而不是构建对象,
int i();也是一样。但是给定实参了情况就不一样,int i(4);这条语句,编译器
能识别出来是创建对象,A a(4);编译器也能识别出来。

堆上创建对象
如果是new创建对象(自定义和内置)
没有参数的话可以写括号,
int* pa = new int();//*pa为0
int* pa = new int;// *pa未知
对于自定义类型而言,写不写括号都是一样的,都会调用无参构造,或有默认值的构造。

explicit关键字使用
explicit关键字的使用主要是为了防止单参构造时产生的隐式转换带来的隐患。
class A
{
public:
   explicitA(int a){}
}
A a = 3;// 这种写法在没有explicit关键字时是可以的,但是可能是误写,
explicit就是来禁止类似这种情况的,有了explicit关键字这种隐式转换被
禁止,编译不过。

拷贝构造函数和赋值运算符重载区别
class noncopyable
{
protected:
    noncopyable(){ }
    ~noncopyable(){ }
private://必须为私有,这样子类里是无法以任何方式访问的
    noncopyable(const noncopyable&);// A a = a1; 右边的是实参
    const noncopyable& operator=(const noncopyable&);// a = a2,右边的a2是实参
};
还要搞清楚一个事,构建对象时,调用的是即将要创建的这个对象的成员函数,搞清楚谁给谁赋值。
class A :private noncopyable
{
public:
    A(A& a):noncopyable(rhs){} // 要显示调用才行,否则基类的是不会被调用的
    const A& operator=(A& rhs){}// 如果子类定义了自己的赋值运算符重载且没有显示调用基类的,那么就不会自动调用基类的
};
为了驳回编译器或标准自动提供的技能,可将相应的成员函数声明为private并且不予实现。

封装性
封装性是对类外而言的,在类型定义里是不起作用的,也即在类型定义域里访问通过对象访问本类是不受任何限制的,
public protected private限制是对类域以外的,在类里面是不起作用的。
class A
{
public:
    const A& A(A& a){this._a = a._a;}
private:
    int _a;
};


默认构造函数是否等价于无参构造
至少他们两个的函数签名和函数名字是一样的,如果这两个都一样,那么编译器还有什么理由能区分它们呢?
所以可以认为他们是一样的,但是无法确认编译器默认的构造实现是怎样的,但是这已经不重要了。
当构造子类时,子类构造函数会调用直接父类的构造,直接父类会调用其直接父类的构造,一直到根类为止,才到出口。
如果你显示指定了调用基类的构造,那没什么可说的,但是只能调用直接父类,调用父类的父类及以上是会报错的。
如果没有显示调用直接父类的构造,那么编译器给你加了,调用的是直接父类的无参构造。
如果基类的赋值操作符函数为私有,那么编译器不会给他的子类生成默认赋值操作符函数,因为子类默认赋值操作函数是
要调用直接父类的赋值操作函数,如果是私有,还调用个毛线,所以编译器就不生成了。
规则是:在没有显示指定直接直接父类构造和赋值操作函数的情况下,子类拷贝构造自动调用直接父类无参构造,
子类赋值操作函数是不会自动调用直接父类的赋值操作符函数的,但是如果是默认的赋值操作符函数,就会一层一层往上调赋值操作函数。
如果子类需要调用父类的赋值操作符函数,只能在函数体里调用,因为只有构造函数才有成员初始化列表调用格式
derived& derived::operator=(const derived& rhs)
{
    if (this == &rhs)
        return *this;
    base::operator=(rhs);
    y=rhs.y;
    return *this;
}
* 如果子类当前被调用的构造(拷贝构造和普通构造)没有显示指定要调用的直接父类的构造,编译器会为其添加调用直接父类无参构造的代码。
* 如果子类赋值操作函数里面没有调用基类的赋值操作函数(可以是直接父类也可以是爷爷类),编译器不会给你添加调用代码的
所以这就是为什么noncopyable可以运作的原理,设成私有的,私有继承也无妨,因为默认的拷贝构造和赋值操作函数都是调用其基类的
拷贝构造和赋值操作函数,一旦你自己定义了,就会干扰这一线路,
*即使你自己写了构造函数,编译器还是可能为你的构造调用直接父类的构造的(你没有显示指定的时候)
*即使你自己写了赋值操作函数,编译器是绝无可能为你添加直接父类的赋值操作函数的。和上面区别。
原创粉丝点击