C++继承的理解

一、类与类之间的三种关系  

  我们都知道类与类之间有三种关系,分别是:

1.代理:一个类的端口集合是另一个类端口集合的子集

例如:

#include<iostream>
using namespace std;

class Arr
{
public:
	void insert_head();
	void insert_tail();
	void delete_head();
	void delete_tail();
};

class stack
{
public:
	void stack_push()
	{
		_a->insert_head();
	}
	void stack_pop()
	{
		_a->delete_head();
	}
private:
	Arr *_a;
};

这就是一个代理类,stack类中的成员方法全部由Arr类中的函数方法实现,即stack类中的端口集合全部是Arr类端口集合的子类。

2.组合、嵌套类     一个类是另一个类的一部分

  组合类:一个类的成员变量是另一个类的对象,即内嵌其他类的对象作为自己的成员

#include<iostream>
using namespace std;

class Date
{
public:
	int year;
	int month;
	int day;
};

class Person
{
private:
	char name[20];
	int age;
	Date birthdate;
};

  其中,Date类就是Person这个类的一部分  

  嵌套类:一个类是嵌套在另一个类里面,我们还拿Date类和Person类来举例子。

#include<iostream>
using namespace std;

class Person
{
public:
   class Date
   {
   public:
	  int year;
	  int month;
	  int day;
   };

private:
	char name[20];
	int age;
	Date birthdate;
};

  嵌套相较组合来说,更能明显看出Date类是Person类的一部分。

  3.第三种就是我们所讲的继承类了

  继承类:一个类是另一种类的一种

继承的本质:同一端口,代码复用

举例:

二、继承方式和访问权限

1.若子类继承基类的方式是public

基类中的权限                             继承方式                                子类中的权限                                 外部的权限

public                                           public                                     public                                            不可访问

private                                         private                                    不可访问                                       不可访问

protected                                     protected                                不可访问                                       不可访问

2.若子类的基类继承的方式是protected

public                                           protected                               不可访问                                        不可访问

protected                                      protected                              不可访问                                         不可访问

private                                          private                                   不可访问                                         不可访问

3.若子类的基类继承的方式是private

public                                           private                                   不可访问                                          不可访问                           

protected                                      private                                   不可访问                                          不可访问

private                                          private                                   不可访问                                           不可访问

三、继承关系中成员方法的关系

重载:同函数名不同参数列表,同一作用域

隐藏:父类和子类中同名方法被隐藏

覆盖:子类中同名同参数同返回值的成员方法覆盖父类中虚成员方法

举例:

这里先举一个隐藏的例子

class Base
{
public:
	void show()
	{
		cout << "Base::void show()" << endl;
	}

	void show(int a)
	{
		cout << "Base::void show(int a)" << endl;
	}

};

class Derive:public Base
{
public:
	void show()
	{
		cout << "Derive::void show()" << endl;
	}

};

int main()
{
	int a = 10;
	Derive derive;
	derive.show();  
	//derive.show(a);          //这句语句报错
	derive.Base::show();
	derive.Base::show(a);
}

  这里子类的成员方法隐藏了基类的成员方法,因为Derive是基类Base的子类,但在我们引用基类中有而子类中没有的成员方法时,却出现了错误,这就是我们所讲的第二个关系——隐藏。这里子类隐藏了基类中的成员方法,那如果我们想要调用基类中的成员方法,我们应该如何做呢?——加作用域。

  覆盖相较其他两种关系较复杂,下面我来详细解释。

  第一,覆盖必须满足的几个条件:

1.只有类的成员函数可以被声明为虚函数,构造函数、全局函数、静态成员函数都不能被声明为虚函数。

2.只有在基类中以virtual关键修饰的成员函数才能作为虚函数被子类覆盖,子类中覆盖版本的virtual加不加都可以。

3.虚函数在子类中的覆盖版本和该函数的原始版本,拥有相同的函数签名:函数名,形参表,常属性。

4.如果基类中的虚函数返回值为非类类型的指针或引用,那么子类的覆盖版本必须和基类初始版本返回类型一致。

5.如果基类中的虚函数返回类类型的指针(A*)或引用(A&),那么允许子类的覆盖版本返回其子类的指针(B*)或引用(B&)——类型协变。

  以上五个条件必须同时满足,才可以去覆盖。

  下面看一段代码:

class Base
{
public:
	virtual void show()
	{
		cout << "Base::show()" << endl;
	}
	int _a;
	int _b;
};

class Derive :public Base
{
public:
	void show()
	{
		cout << "Derive::show()" << endl;
	}
	int _c;
	int _d;
};

int main()
{
	Derive derive;
	Base *ps = &derive;

	ps->show();
}

虽然ps是Base类的一个指针,但ps的show方法却指向的Derive的show方法,这就是因为Derive中的show方法覆盖了Base中的show方法。

猜你喜欢

转载自blog.csdn.net/weixin_42736024/article/details/82975038
今日推荐