继承的概念

继承机制是面向对象程序设计使代码可以复用的重要手段。它允许我们在原有类的特性的基础上进行扩展,增加方法和属性,这样产生新的类,称派生类。

继承的定义

代码语言:javascript

AI代码解释

//class 派生类名 :继承方式 基类名
class Person
{
  //....
};

class Studen:public Person//定义继承
{
  //...
};
*************************************************************
#include<iostream>
#include<string>
using namespace std;

class Person
{
public:


protected:
	string _name;
	string _address;
	int _age=18;
	string _tel;
};

class teacher:public Person
{
public:
	void identity()
	{
		cout << "teacher:" << "void identity()" << endl;
	}

protected:
	string _title;
};

class student:public Person
{
public:
	void identity()
	{
		cout << "student:" << "void identity()" << endl;
	}
protected:
	int _stuid;
};

int main()
{
	student s;
	teacher t;

	s.identity();
	t.identity();

	return 0;
}

继承的方式(与访问限定符很像)

  1. public继承
  2. protected继承
  3. private继承
继承基类(父类)成员访问方式的变化

基类private成员在派⽣类中无论以什么方式继承都是不可见的。

基类private成员在派⽣类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派⽣类中能访问,就定义为protected。

实际上⾯的表格我们进行⼀下总结会发现,基类的私有成员在派⽣类都是不可见。基类的其他成员 在派生类的访问方式==Min(成员在基类的访问限定符,继承⽅式),public >protected> private。

使⽤关键字class时默认的继承方式是private,使⽤struct时默认的继承方式是public,不过最好显示的写出继承方式。

在实际运⽤中⼀般使⽤都是public继承,⼏乎很少使用protetced/private继承,也不提倡使用 protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。

继承类模板

代码语言:javascript

AI代码解释

namespace liu
{
	//template<class T>
	//class vector
	//{};
	// stack和vector的关系,既符合is - a,也符合has - a
	template<class T>
	class stack : public std::vector<T>
	{
	public:
		void push(const T& x)
		{
			// 基类是类模板时,需要指定⼀下类域,
			// 否则编译报错: error C3861 : “push_back”:找不到标识符
			// 因为stack<int>实例化时,也实例化vector<int>了

			// 但是模版是按需实例化,push_back等成员函数未实例化,所以找不到
			//push_back(x);
			vector<T>::push_back(x);
			//push_back(x);
		}
		void pop()
		{
			vector<T>::pop_back();
		}
		const T& top()
		{
			return vector<T>::back();
		}
		bool empty()
		{
			return vector<T>::empty();
		}
	};
}

template<class Container>
void Print(const Container& c)
{
  //这里需要注意,因为这里是模板,所以需要在Container前面加typename。
  //因为这是一个模板,Container是模板参数,编译器不知道Container是什么类型,它可能是一个内嵌类型,也可能是一个静态成员变量,因此,我们需要在前面加上一个typename告诉编译器Container是一个类型,
  typename Container::const_iterator it1=c.begin();
  while(it1!=c.end())
  {
    cout<<*it1<<endl;
     ++it1;
  }
  cout<<endl;
}

int main()
{
  
return 0;
}
基类与派生类间的转换
  • public继承的派⽣类对象可以赋值给基类的指针/基类的引用。这⾥有个形象的说法叫切片或者切割。寓意把派生 类中基类那部分切出来,基类指针或引⽤指向的是派⽣类中切出来的基类那部分
  • 基类对象不能赋值给派生类对象。
  • 基类的指针或者引用可以通过强制类型转换赋值给派⽣类的指针或者引用。但是必须是基类的指针 是指向派生类对象时才是安全的。这里基类如果是多态类型,可以使用RTTI(Run-TimeType Information)的dynamic_cast 来进⾏识别后进行安全转换。(ps:这个我们后面类型转换章节再单独专门讲解,这里先提一下
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐