函数传值 复制构造函数 深度拷贝

class A{
	int *m_pi;
public:
	A()
	{
		m_pi = new int;
	}
	~A()
	{
		delete m_pi;
	}
};

void func(A _a)
{
	int a = 0;
}

void main()
{ 
	A a;
	func(a);
}


运行后崩溃,原因是当调用func时,产生一个临时对象,并未调用构造函数,调用默认的位拷贝复制构造函数,然后析构掉了 m_pi 的内存,程序结束析构a时崩溃,解决方案是重载拷贝构造函数


class A
{
	int *m_pi;
public:
	A()
	{
		m_pi = new int;
	}
	~A()
	{
		delete m_pi;
	}
	A(A &_a)
	{
		m_pi = new int;
		*m_pi = *_a.m_pi;
	}
};

void func(A _a)
{
	int a = 0;
}

再考虑,在A中加一个CArray对象


class A
{
	int *m_pi;
	CArray <int,int &> m_arr;
public:
	A()
	{
		m_pi = new int;
	}
	~A()
	{
		delete m_pi;
	}
	
};

void func(A _a)
{
	int t = 0;
}

主函数:

    A a;
    func(a);


编译报错:

“CObject::CObject”: 无法访问 private 成员(在“CObject”类中声明)
原因:func传入实参后会生成临时对象,用默认的拷贝构造函数初始化临时对象(因为这里未定义拷贝构造函数),而默认的拷贝构造函数会依次调用A类成员的拷贝构造函数,如果未定义,则会调用默认的,对于CArray来说,虽然未定义了拷贝构造函数,但其基类CObject定义了,但为private权限,编译报错。

private:
    CObject(const CObject& objectSrc);              // no implementation
    void operator=(const CObject& objectSrc);       // no implementation

对于赋值操作符,同样的
主函数
    A a;
    A b;
    b = a;       // 不同于 A b = a  出现第一种错误,编译器?

报错:
“CObject::operator =”: 无法访问 private 成员(在“CObject”类中声明)


解决方案:

重载操作符

    A &operator=(A &)
    {
        return *this;
    }

定义拷贝构造函数

    A(A &)
    {
    }


再考虑

class A
{
	int m_a;
	CArray <int,int> m_arr;
public:
	A(int i){};
};

void main()
{

	A a;
	CArray<A,A &> arr;
	arr.Add(a);
}

报错:
“A”没有合适的默认构造函数可用
原因:
可能是因为进入CArray的类型必需有不带参数构造函数,我们将带参数构造函数去掉
http://hi.baidu.com/idealsoft/item/4de85dcac49b2c2847d5c07d
报错:
“CObject::operator =”: 无法访问 private 成员(在“CObject”类中声明)
原因:

arr.Add(a) 时,会调用A的=,而未定义,则逐次调用成员的,包括CArray成员m_arr,因为Add函数的签名要求输入参数的类型为A&,所以当编译器编译语句:arr.Add(a); 时会自动将a强制转换成A的引用,即将这条语句编译成:A& newElement = b; arr.Add(newElement); 赋值操作就这样出现了!解决方案:定义=操作符

    A &operator=(A&)
    {
        return *this;
    }

http://blog.csdn.net/vincent_lon/article/details/2950218


此外,若将CArray参数改为传值CArray<A,A> arr;,则报错:

“CObject::CObject”: 无法访问 private 成员(在“CObject”类中声明)


add 的参数变为值传递,需要拷贝构造函数支持,而我们的类没有,CArray同样没有,CObject有,但是私有,所以编译报错,解决方案为定义拷贝构造函数:

    A(A &){}
    A(){}

别忘了再定义一个无参数构造函数


结论:当你的类有CArray成员时,

1 值类型,为类准备无参数构造函数,拷贝构造函数和=重载函数。

2 引用类型,=操作符,无参数构造函数



ps : 2014.6.18

“CObject::operator =”: 无法访问 private 成员(在“CObject”类中声明)

“CObject::CObject”: 无法访问 private 成员(在“CObject”类中声明)


CArray 继承自 CObject, 而CArray只显式定义了无参数默认构造函数,而没有定义拷贝构造和赋值操作符重载函数,A在未定义相关函数的情况下进行拷贝或赋值操作时,

依次调用类体各成员对象的拷贝和赋值操作符重载函数,对于CArray对象,由于未显式定义拷贝和赋值操作符重载函数,故编译器在自动生成的 copy及”=“函数中,调用基类CObject 的拷贝构造 和 ”=“操作符函数,而这两个函数正被CObject声明为private权限,即使在派生类CArray中亦无法访问。


得出:

在设计一个基类时,

1.禁止该类被直接实例化,则将构造函数申明为 private or protected,当申明为private时,该类及其所有派生类都无法实例化,如:

class A
{
private:
	A(){}
};

class B : public A
{
public:
	B(){}
};

error C2248: “A::A”: 无法访问 private 成员(在“A”类中声明)


2.如果处于安全考虑,强制要求其派生类在显式定义 复制控制(拷贝构造和赋值操作符函数),则可将 2个复制控制函数申明为private,如果申明为 protected,则只能在类及派生类体内进行对象复制操作。






转载于:https://www.cnblogs.com/silyvin/archive/2013/05/07/9106894.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值