[C++学习笔记] is-a继承关系——公有继承(part 1)

  • 前言

今天继续更新C++的学习笔记,这次涉及的主题是类继承。类继承总共有三种,分别是公有类继承(is-a关系,或者is-a-kind-of关系),私有继承以及保护继承。为了简便,这篇文章主要记录的公有继承(is-a关系)。

注:有问题请在评论区或者通过其它可能的方式指正。

目录

1.基本概念:

2. 虚方法的使用——如何给基类中的函数增加新功能?

3.补充说明——虚方法的使用注意事项

1.基本概念:

  • 派生类(Derived Class)和基类(based Class)

公有继承的一般的定义方式为

// 基类
class Show
{
    private: 
        ...// 私有部分
    public: 
        ...//公有部分
};

// 派生类(子类),采用冒号进行声明
class ShowPro: public Show
{
    private: 
        ...// 私有部分
    public: 
        ...//公有部分
};

上面的代码里包含了两种定义方式,分别是普通类的定义方式以及派生类(公有类继承后的类)的定义方式。

其中,类Show即为基类,相当于原本的财产拥有者。类ShowPro即为派生类,是继承了Show类属性(含成员变量和成员函数)的财产继承人。

  • is-a继承关系(三种中的一种),属于公有继承(继承的是公有的财产)

首先,继承的对象是基类,而继承的部分便是基类中的public部分。因此,当你想用派生类(Derived Class)去访问基类(based Class)prviate部分时,这种行为将会遭到报错处理。(因为private部分没有被继承)。当然,这也可以理解为private 本身起到的保护作用。解决措施是,将需要访问的部分放入protected中。

  • protected 的作用

protected 在一般情况下和private 一样,具有保护功能。但在公有类继承中则会显示出不同的作用;例如,派生类可以访问protected 中成员(包括函数和变量),而不会像访问protected中成员一样,被禁止。

  • 公有继承的目的和作用

公有继承的可以使得派生类获得基类的中的方法和变量的使用权限(仅限被继承的部分),并可以根据需要调用这些方法或者修改这些变量。这样带来的好处自然是“方便和高效”!因为这样相当于在原本已经盖好的房子上进行作业,直接省去了重新编写一些基本方法的工作量。

2. 虚方法的使用——如何给基类中的函数增加新功能?

class ShowPro: public Show
{
    private: 
        ...// 私有部分
    public: 
        ...//公有部分
};

在介绍虚方法之前,我们先简单的介绍下该方法的来由。上面我们谈到,我们可以采用公有继承的方式(如上代码所示)来继承基类中已经编写好的函数和变量,而且我们还拥有访问和使用这些继承到的“财产”。但还有的一个关键问题是,如果你还想要对这些已经编写好的函数进行一些“功能补充”,咋办?

“我们就想改进改进,优化优化,不行吗?”

“好吧,当然可以!”

C++提供了虚方法来完成这个工作。我们仅需将想要修改的方法,利用关键字Virtual(虚拟的)

可将类中的成员函数定义为虚方法。这样便可以获得修改的权限。

具体示例如下:

/*一个名称空间*/
namespace SHOW
{
	/*基类*/
	class Show
	{
		private:
			int gauss;
			std::string words ;
		public:
			Show():gauss(0),words("hello I am Show"){};
			Show(const int i,const std::string s):gauss(i),words(s){};
// 将其声明为虚基类方法,我们将可以在使得派生类的方法可修改
			virtual void showstr() 
			{
				std::cout << words << " (" << gauss << ")" << std::endl;
			};
	};
	
	/*派生类*/
	class ShowPro: public Show
	{
		private:
			int age = 0;
		public:
			ShowPro();
			ShowPro(const int i,const int age,const std::string s);
// 派生类的virtual只起标记作用,但不介意省去,而是留着作为一种标记
			virtual void showstr(); 
	};
};

这里的showstr()成员函数在基类和派生类中都存在。换言之,我们在派生类(继承财产的继承人)中重新定义了这个函数,使得它具备更多功能。

3.补充说明——虚方法的使用注意事项

以下是需要知道构造函数、析构函数等概念才能深刻了解的部分,这里附上使得文章完整些。需要注意的是,这里我用了比较通俗的解释(并加入了自己的理解),如果想要查严谨的说明,请查阅其它资料。

(1)虚方法不能用于构造函数,因为不同的对象需要进行的初始化方法一般是不同的,这样的使用没有意义。
(2)析构函数必须是virtual的,因为一般delete的类对象不同(delete配合new使用,用于给指针分配内存),这样防止内存泄漏,并使得效率更高。
(3)虚方法只适用于成员函数,因此友元函数是不能使用虚方法的,因为友元函数不是成员函数。
(4)若是具有函数重载的成员函数被设置为虚方法,则所有的重载类型都要被设置为虚方法(否则会被隐藏,失去作用)

对于(4),这里特别进行说明。

函数重载:如果没掌握这个概念,可以这样简单理解,函数重载相当于一个函数名有多种定义,形象地表述就是"很多人都叫张三,但他们却都不是同一个人,各自做着不同的工作"

现在对(4)进行解释,如下代码中,我们对运算符成员函数operator = 进行了函数重载,如果将这种经过重载的函数声明为虚方法,则要将所有的=都声明为虚方法。否则没有声明的函数将会被隐藏,失去作用。

class Array
	{
		private:
			int len; 
			char * str;
		public:

			/*重新定义构造函数*/
			Array() ; 
			Array(const char * s); 
			Array(const Array & arr); 

			/*我们也需要重构赋值构造函数*/
            /*这里我们对=使用了函数重载*/
			Array & operator = (const Array & arr); 
			Array & operator = (const char * s);		
			
			/*析构函数*/
			~Array();
	};

本文最新修改于2022-03-03

 

你可能感兴趣的:(C++学习笔记,c++,学习,开发语言)