深入解析C++继承机制:从基础到高级特性

深入解析C++继承机制:从基础到高级特性

在C++编程中,继承是一种强大的机制,它允许我们通过创建新的类(派生类)来扩展已有的类(基类)的功能。本文将通过一系列示例代码,深入解析C++继承的多种特性,包括单继承、多继承、继承方式(public、protected、private)、构造与析构、同名成员处理、静态成员继承、菱形继承问题以及虚继承的解决方案。

一、单继承:扩展基类功能

单继承是C++中最基本的继承形式,派生类继承基类的成员,并可以添加新的成员或覆盖基类的成员。

示例代码解析

继承.cpp文件中,test1_1函数展示了单继承的典型用法。baseclass1是一个基类,定义了网站页面的通用部分(如头部、左侧边栏和底部)。派生类sonclass11sonclass12sonclass13分别表示不同的子页面,它们继承了基类的通用部分,并添加了各自的内容。

cpp复制

sonclass11 java;
java.header();
java.left();
java.footer();
java.content();

运行结果:

复制

网站固定首页
网站固定左侧边栏
网站固定底页
子页1内容

关键点

  • 派生类继承了基类的公共成员(headerfooterleft)。

  • 派生类可以添加自己的成员(如content)。

二、继承方式:public、protected、private

C++提供了三种继承方式:publicprotectedprivate,它们决定了基类成员在派生类中的访问权限。

示例代码解析

继承.cpp文件中,test1_2函数展示了三种继承方式的差异。

公共继承(public

cpp复制

class sonclass21 : public baseclass2
{
public:
	void func()
	{
		m_a = 1; // 可访问
		m_b = 2; // 可访问
		// m_c = 3; // 不可访问,基类私有成员
	}
};
  • 基类的publicprotected成员在派生类中保持原有访问权限。

  • 基类的private成员在派生类中不可访问。

保护继承(protected

cpp复制

class sonclass22 : protected baseclass2
{
public:
	void func()
	{
		m_a = 1; // 可访问
		m_b = 2; // 可访问
		// m_c = 3; // 不可访问,基类私有成员
	}
};
  • 基类的publicprotected成员在派生类中变为protected

  • 基类的private成员在派生类中不可访问。

私有继承(private

cpp复制

class sonclass23 : private baseclass2
{
public:
	void func()
	{
		m_a = 1; // 可访问
		m_b = 2; // 可访问
		// m_c = 3; // 不可访问,基类私有成员
	}
};
  • 基类的publicprotected成员在派生类中变为private

  • 基类的private成员在派生类中不可访问。

关键点

  • 不同的继承方式会影响基类成员在派生类中的访问权限。

  • 私有继承通常用于实现细节的封装,而不是扩展功能。

三、构造与析构:继承中的构造顺序

在继承中,构造函数的调用顺序是:基类构造函数 → 派生类构造函数。析构函数的调用顺序是:派生类析构函数 → 基类析构函数。

示例代码解析

继承.cpp文件中,test1_4函数展示了继承中的构造和析构顺序。

cpp复制

class baseclass4
{
public:
	baseclass4()
	{
		cout << "构造base" << endl;
	}
	~baseclass4()
	{
		cout << "析造base" << endl;
	}
};

class sonclass4 : public baseclass4
{
public:
	sonclass4()
	{
		cout << "构造son" << endl;
	}
	~sonclass4()
	{
		cout << "析造son" << endl;
	}
};

运行结果:

复制

构造base
构造son
子类继承父类,构造父类,构造子类,析构子类,析构父类
析造son
析造base

关键点

  • 构造函数的调用顺序是:基类 → 派生类。

  • 析构函数的调用顺序是:派生类 → 基类。

四、同名成员处理:隐藏与覆盖

在继承中,如果派生类和基类有同名成员,派生类的成员会隐藏基类的成员。如果需要访问基类的同名成员,可以通过作用域解析运算符::来实现。

示例代码解析

继承.cpp文件中,test1_5函数展示了同名成员的处理方式。

cpp复制

class baseclass5
{
public:
	int m_a = 0;
	void func() const
	{
		cout << "base func()" << endl;
	}
	void func(int a) const
	{
		cout << "base func(int a)" << endl;
	}
};

class sonclass5 : public baseclass5
{
public:
	int m_a = 1;
	void func() const
	{
		cout << "son func()" << endl;
	}
};

运行结果:

复制

1
0
son func()
base func()
base func(int a)

关键点

  • 派生类的成员会隐藏基类的同名成员。

  • 可以通过基类名::成员名来访问基类的同名成员。

五、静态成员继承:静态成员的特殊性

静态成员属于类,而不是类的对象。在继承中,静态成员的行为与其他成员略有不同。

示例代码解析

继承.cpp文件中,test1_6函数展示了静态成员的继承特性。

cpp复制

class baseclass6
{
public:
	static int m_a;
	static void func()
	{
		m_a = 10;
		cout << m_a << endl;
	}
};
int baseclass6::m_a = 1;

class sonclass6 : public baseclass6
{
public:
	static int m_a;
	static void func()
	{
		m_a = 100;
		cout << m_a << endl;
	}
};
int sonclass6::m_a = 2;

运行结果:

复制

2
1
1
1
100
10

关键点

  • 静态成员可以通过类名直接访问。

  • 派生类可以继承基类的静态成员,但可以通过覆盖来定义自己的静态成员。

六、多继承:复杂的继承关系

C++支持多继承,即一个类可以继承多个基类。然而,多继承可能会导致一些问题,如菱形继承问题。

示例代码解析

继承.cpp文件中,test1_7函数展示了多继承的用法。

cpp复制

class baseclass7_1
{
public:
	int m_a = 1;
};

class baseclass7_2
{
public:
	int m_a = 2;
	int m_b = 3;
};

class sonclass7 : public baseclass7_1, public baseclass7_2
{
public:
	int m_b = 4;
	int m_c = 5;
};

运行结果:

复制

1
2
3
4
5
建议不使用多继承,同名时比较混乱

关键点

  • 多继承可能导致同名成员的冲突。

  • 建议尽量避免使用多继承,以减少复杂性和潜在的错误。

七、菱形继承问题及其解决方案:虚继承

菱形继承是多继承中常见的问题,它会导致派生类继承多份基类的相同数据。为了解决这个问题,C++引入了虚继承。

示例代码解析

菱形继承.cpp文件中,test1_8函数展示了虚继承的用法。

cpp复制

class animal
{
public:
	int m_age = 0;
};

class sheep : virtual public animal
{
public:
	string m_color = "black";
};

class tuo : virtual public animal
{
public:
	string m_sex = "man";
};

class sheeptuo : public sheep, public tuo
{
public:
	int height = 0;
};

运行结果:

60 10 blue none

关键点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值