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,则只能在类及派生类体内进行对象复制操作。