类继承中的一些细节问题

类的继承中的一些细节问题

请阅读如下程序

class A {
public:
	A() :a(0) {}
	~A() {
		a1 -= a;
	}
private:
	int a;
protected:
	static int a1;
};
class B :public A{
public:
	B() :A() {}
	~B(){}
};
int A::a1 = 0;
int main() {
	B* b1 = new B;
	delete b1;
	return 0;
}

  在这段程序中有一个隐藏的问题:A类的两个数据成员,a的访问限定符为private,a1的访问限定符为protected。故a在B类中不可访问,a1在B类中可以访问。那么在执行B* b1 = new B; 这条语句时,应当是通过B类的构造函数调用A类的构造函数。那么程序是否会跳过B类不可访问的a成员的初始化而只执行a1成员的初始化呢?
  如果程序没有初始化a,那么在执行析构时,在执行到a1-=a; 的这条语句时就会发生错误,因为此时a并没有被初始化就被直接使用。程序的执行结果是,该条语句执行正常,a的值和a1的值都被正常初始化为0。这说明,在类的继承中,派生类调用基类的构造函数,而基类的构造函数正常对所有其初始化的成员进行初始化,而不会跳过派生类中不可访问的成员,只不过private的成员在派生类中不可访问罢了。之前在某些技术博客中看到了所谓“会忽略派生类中不可访问的成员”的说法应该是错误的。

  这有时候会导致一些问题。请看下面的代码:

class A {
public:
	A() :a(0),a1(0){}
	~A() {
		a1 -= a;
		a2--;
	}
private:
	int a;
	static int a2;
protected:
	int a1;
};
class B :public A{
public:
	B() :A() {}
	~B(){}
};
int A::a2 = 0;
int main() {
	B* b1 = new B;
	delete b1;
	return 0;
}

  假设我们希望static int A::a2是一个可以记录程序中A类成员个数的计数器。因此我们在A类的析构函数中写入的a2–; 的语句。但是当我们定义了一个B类的对象,并删除该对象时,会调用A类的析构函数,会正常执行a2–; 的语句。A类的对象并没有减少,而A类对象的计数器却减少了一个,这显然是不行的。解决方法是,我们将a2声明为protected,然后在B类的析构函数中先把a2++; 这样就通过一种暴力的方法解决了问题。
代码如下

class A {
public:
	A() :a(0),a1(0){}
	~A() {
		a1 -= a;
		a2--;
	}
private:
	int a;
protected:
	int a1;
	static int a2;
};
class B :public A{
public:
	B() :A() {}
	~B(){
		a2++;
	}
};
int A::a2 = 1;
int main() {
	B* b1 = new B;
	delete b1;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值