二十五、继承(二) 不能自动继承的成员函数、继承与构造函数、友元关系与继承、静态成员与继承

本文详细解析了C++中的继承机制,特别是构造函数、析构函数和=运算符为何不能被继承的原因。同时介绍了如何在派生类中正确地初始化基类成员,并探讨了友元关系、静态成员在继承中的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、不能自动继承的成员函数
          有三种函数不能被继承,构造函数,析构函数和=运算符,基类的构造函数和析构函数只负责对基类数据成员的初始化和清理,因为基类并不知道派生类有哪些数据成员。=运算符和构造函数功能类似,所以也不能被继承。
二、继承与构造函数
          基类的构造函数不被继承,所以派生类中需要声明自己的构造函数来初始化新增的数据成员。在声明构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化(调用基类构造函数完成)。为了在派生类中调用基类构造函数,派生类的构造函数需要给基类的构造函数传递参数。在构造派生类的时候,先调用基类的构造函数,在调用派生类的对象函数。
例子:
#include <iostream>
using namespace std;
class ObjectB
{
public:
	ObjectB(int objb) : objb_(objb)
	{
		cout<<"ObjectB ..."<<endl;
	}
	~ObjectB()
	{
		cout<<"~ObjectB ..."<<endl;
	}
	int objb_;
};

class ObjectD
{
public:
	ObjectD(int objd) : objd_(objd)
	{
		cout<<"ObjectD ..."<<endl;
	}
	~ObjectD()
	{
		cout<<"~ObjectD ..."<<endl;
	}
	int objd_;
};

class Base
{
public:
	Base(int b) : b_(b), objb_(111)
	{
		cout<<"Base ..."<<endl;
	}
	Base(const Base& other) : objb_(other.objb_), b_(other.b_)
	{

	}
	~Base()
	{
		cout<<"~Base ..."<<endl;
	}
	int b_;
	//对象组合
	ObjectB objb_;
};

class Derived : public Base
{
public:
	Derived(int b, int d) : d_(d), Base(b), objd_(222)
	{
		cout<<"Derived ..."<<endl;
	}
	Derived(const Derived& other) : d_(other.d_), objd_(other.objd_), Base(other)
	{

	}
	~Derived()
	{
		cout<<"~Derived ..."<<endl;
	}
	int d_;
	ObjectD objd_;
};

int main(void)
{
	Derived d(100, 200);
	cout<<d.b_<<" "<<d.d_<<endl;

	Base b1(100);
	Base b2(b1);
	cout<<b2.b_<<endl;

	Derived d2(d);
	return 0;
}
运行结果:

内存对象模型:

三、友元关系与继承
          友元关系不能被继承。友元关系是单向的,是不能传递的,也是不能被继承的。
四、静态成员与继承
          静态成无所谓继承。静态成员在内存中的静态存储区,对于类的静态变量来说,即使类没有实例也可以访问其静态变量。如果有实例的话,那么静态变量被所有实例共享。对于基类包含静态成员的派生类来说,基类和派生类共享一块内存,也就是说,基类和派生类共享一个静态变量。
#include <iostream>
using namespace std;
class Base
{
public:
	Base(int t) :b(t){}
	static void show()
	{
		cout<<"Base show"<<endl;
	}
	static int a;
	int b;
};
int Base::a = 99;
class Derived : public Base
{
public:
	Derived(int t):Base(t){}
	static void show()
	{
		cout<<"Derived show"<<endl;
	}
};
int main(void)
{
	Base base(10);
	Derived d(200);
	cout<<"static Base::a="<<Base::a<<endl;
	cout<<"non static Base::b="<<base.b<<endl;
	cout<<"static Derived::a="<<Derived::a<<endl;
	cout<<"non static Derived::b="<<d.b<<endl;
	d.show();
	//d.Base::show();
	return 0;
}
结果:

五、需要在初始化列表初始化的情况总结
  • const成员和引用成员(因为两者都需要在定义的时候初始化,对于类成员来说,初始化只能在构造函数中)
  • 基类的构造(没有默认构造函数的情况下)和组合对象成员(没有默认构造函数的情况下)
          对象的构造先调用基类对象成员构造函数,然后调用基类构造函数,接着调用派生类对象成员的构造函数,最后调用派生类的构造函数。析构的顺序和构造正好相反。如果类包含多个对象成员,那么对象成员的构造顺序是和声明顺序相同的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值