VS2008编译时error C2248处理方法

1.问题提出

类中包含CList模板类,且CList的元素是派生自CObject的自定义类时;编译器报错信息error C2248:“CObject::operator=”无法访问private成员(在“CObject”类中声明)”

2.问题分析

原因是与C++类的“复制构造函数”与“复制操作符”有关。对于一个C++类来说,需要指定创建、复制、赋值和撤销该类型的对象时会发生什么?这是通过定义特殊的成员函数-构造函数、复制构造函数、赋值操作符和析构函数来实现的。如果类没有显式定义这些函数,则会使用默认函数。通过MFC产生的派生自CObject类或其派生类的自定义类,向导都会自动产生构造函数和析构函数,因此大家对这两个函数是比较熟悉的。而另外两个特殊函数复制构造函数和复制操作符则没有自动生成,如果在类中没有显式定义这两个函数,则类会使用默认复制构造函数和默认赋值操作符。

默认赋值操作符的功能是对类的所有非静态成员变量进行赋值处理。对于类B,如果没有显式的定义其赋值操作符,则类会使用默认的赋值操作符,对CList类型的b进行赋值,此时会调用类型A的赋值操作符,而类A也没有定义复制操作符,因此会调用其父类的赋值操作符,直到调用CObject类的赋值操作符“=”;而CObject类的赋值操作符的访问权限是private,因此编译器报错。

3.问题解决
解决该问题的方法如图中红色部分所示,类A重载赋值操作符,并且将其访问权限设置为public,则类B的默认赋值操作符将会调用类A的重载赋值操作符,而不再去调用类A的默认赋值操作符。

解决方法:在自定义类中重载“=”操作符,并且将其声明为public,即可。

class A:public CObject

{

  int x;

 A& operator=(const A& a)

 {

   return *this;

 }

};

class B

{

 CListb;

4.问题思考

4.1 类B重载赋值操作符,类A是否就可以不用重载赋值操作符了?

当类B重载了赋值操作符,在该操作符中也要对类B的成员变量包含A的CList变量进行赋值,还是需要调用类A的赋值操作符,因此此时类A还是要重载操作符。

4.2 类A要重载赋值操作符,为什么不用重载复制构造函数?

类B的默认复制构造函数此时会调用类A的默认复制构造函数,最后调用CObject的构造函数,而CObject的构造函数访问权限是public,可以访问。所以不需要重载复制构造函数。

4.3 如果类A本身就是基类而没有父类,那么A是否还需要重载复制操作符?

从图中可以看到,如果类A本身就是基类,则类B的默认赋值操作符会调用类A的默认赋值操作符,此时流程到此终止,不会向下进行。


你可能感兴趣的:(VC编程)