C++:继承
一 继承的概念及定义
1.1继承的概念
继承 (inheritance)机制是⾯向对象程序设计 使代码可以复⽤ 的最重要的⼿段。
继承是在已有类特性的基础上进⾏扩展,增加⽅法(成员函数)和属性(成员变量),这样产⽣新的类。原来的类称为基类(父类);新类称为派⽣类(子类)。 继承可以提高代码的复用性,呈现出 ⾯向对象程序设计的层次结构。 以前我们接触的函数层次的复⽤,继承是类设计层次的复⽤。
【实例】
代码语言:javascript
AI代码解释
//普通方式-设计一个学生类和一个老师类型
class Student
{
public:
// 进⼊校园/图书馆/实验室刷⼆维码等⾝份认证
void identity()
{
// ...
}
// 学习
void study()
{
// ...
}
protected:
string _name = "peter"; // 姓名
string _address; // 地址
string _tel; // 电话
int _age = 18; // 年龄
int _stuid; // 学号
};
class Teacher
{
public:
// 进⼊校园/图书馆/实验室刷⼆维码等⾝份认证
void identity()
{
// ...
}
// 授课
void teaching()
{
//...
}
protected:
string _name = "张三"; // 姓名
int _age = 18; // 年龄
string _address; // 地址
string _tel; // 电话
string _title; // 职称
};
//我们看到没有继承之前我们设计了两个类Student和Teacher,Student和Teacher都有姓名 / 地址 /
//电话 / 年龄等成员变量,都有identity⾝份认证的成员函数,设计到两个类⾥⾯就是冗余的。
//继承方式把两个类中的公有成员提取出来,设计成一个类,在继承这个类
class Person
{
public:
// 进⼊校园/图书馆/实验室刷⼆维码等⾝份认证
void identity()
{
// ...
}
protected:
string _name = "peter"; // 姓名
string _address; // 地址
string _tel; // 电话
int _age = 18; // 年龄
};
class Student :public Person
{
public:
// 学习
void study()
{
// ...
}
protected:
int _stuid; // 学号
};
class Teacher :public Person
{
public:
// 授课
void teaching()
{
//...
}
protected:
string _title; // 职称
};
1.2继承的定义
1.2.1定义格式
下⾯我们看到Person是基类,也称作⽗类。Student是派⽣类,也称作⼦类。继承方式和访问限定符一样有三种:public继承、protected继承、private继承。

1.2.2类继承基类方式改变对应成员访问⽅式的变化
继承和访问限定符分类如下:

继承基类的方式不同不然会导致,访问基类成员的方式不同,具体如下:

规则
1. 基类private成员在派⽣类中⽆论以什么⽅式继承都是不可⻅的。 这⾥的不可⻅是指基类的私有成员还是被继承到了派⽣类对象中,但是语法上限制派⽣类对象不管在类⾥⾯还是类外⾯都不能去访问它。 (即无法在派生类中显示调用,可以通过在基类中设计一个公有函数进行访问) 2. 基类private成员在派⽣类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派⽣类中能访问,就定义为protected。 保护成员限定符是因继承才出现的。 3. 基类的私有成员无论任何生成派生类在派⽣类都是不可⻅。 基类的其他成员在派⽣类的访问⽅式 == Min(成员在基类的访问限定符,继承⽅式),public > protected > private。 4. 使⽤ 关键字class时默认的继承⽅式是private ,使⽤ struct时默认的继承⽅式是public , 不过最好显⽰的写出继承⽅式。 注意: 在实际运⽤中⼀般使⽤都是public继承,⼏乎很少使⽤protetced/private继承,也不提倡使⽤protetced/private继承,因为protetced/private继承下来的成员都只能在派⽣类的类⾥⾯使⽤,实 际中扩展维护性不强。
【示例】
代码语言:javascript
AI代码解释
//1基类中的private(私有成员)不管与什么继承方式都在派生类中不可见,
// 但是不一定是不能使用,可以在基类中设计一个公有函数进行访问。例如父亲的私房钱虽然不可见,但是可以通过简介的方式得到(全部告诉妈妈)。
//2基类中的其他类型成员在派生类中的限制是,基类中成员变量的访问限定符和派生类的继承方式两种访问限定符种更小的一个
class Person
{
public:
// 进⼊校园/图书馆/实验室刷⼆维码等⾝份认证
void identity()
{
// ...
}
//为了满足基类中的私有成员可以在派生类中可见,在基类中设计一个公有函数进行访问。
void func()
{
++_age;
}
protected:
string _name = "peter"; // 姓名
string _address; // 地址
string _tel; // 电话
private:
int _age = 18; // 年龄
};
class Student :public Person
{
public:
// 学习
void study()
{
// ...
_name = "张三";
}
protected:
int _stuid; // 学号
};
class Teacher :public Person
{
public:
// 授课
void teaching()
{
//...
//_age++;基类中的(private)私有成员,不管与哪种方式继承,都是在派生类中不可见
}
protected:
string _title; // 职称
};
int main()
{
Student s;
Teacher t;
//s._name;基类中的(protected)保护成员,通过tublic(公有继承)是派生类中的保护成员,在类外不可见,在类中可将
s.identity();//基类中的公有成员,通过tublic(公有继承)是派生类中的公有成员;
s.func();//对基类中的私有成员进行访问;
t.identity();
return 0;
}
1.2.3 继承类模板【类继承类似】
【示例】实现栈以前是使用组合(一个类中有一个类,后面会讲)这里通过继承类模板来实现
代码语言:javascript
AI代码解释
//原来实现一个栈是一个组合(类中有一个类)后面会讲
template<class T,class Container>
class Stack
{
private:
Container _con;
};
//继承-模板继承
//私有模板继承私有一个栈
namespace wzy
{
//
template<class T>
class stack : public std::vector<T>//如果展开了std就不用指定
{
public:
void push(const T& x)
{
// 基类是类模板时,需要指定⼀下类域,
// 否则编译报错:error C3861: “push_back”: 找不到标识符
// 因为stack<int>实例化时,也实例化vector<int>了
// 但是模版是按需实例化,push_back等成员函数未实例化,所以找不到
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();
}
};
}
int main()
{
wzy::stack<int> st;
st.push(1);
st.push(2);
st.push(3);
while (!st.empty())
{
cout << st.top() << " ";
st.pop();
}
return 0;
}
二 基类和派⽣类间的转换
2.1不同的转换方式
2.1.1会产生临时变量
前面不同类型变量自己支持类型转换,并且之间会产生临时对象(由于临时对象具有常性所以一般用const来修饰转换的结果),例如int和double类型之间的转换是支持的,只是可能由于精度的原因值可能改变。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)