C++ 继承机制详解
面向对象编程的三大特性之一是继承。如果说封装是屏蔽细节,那么继承就是复用代码并建立类之间的层次关系。今天我们来深入探讨继承中的访问控制、作用域隐藏以及派生类的默认成员函数行为。
继承的定义与访问权限
想象一下,学生和教师都有姓名、住址和电话,但教师有职称,学生有学号。我们可以将共性封装在 Person 基类中,差异封装在 Student 和 Teacher 派生类中。
class Person {
public:
// 身份认证
void identity() {
cout << "void identity()" << _name << endl;
}
protected:
string _name = "张三";
string _address;
string _tel;
private:
int _age = 18;
};
class Student : public Person {
public:
void study() { /* ... */ }
protected:
int _stuid;
};
关于私有成员的真相:
父类的 private 成员在子类中是不可见的。但这并不意味着它们没有被继承。实际上,它们被包含在子类对象内存布局中,只是语法上禁止直接访问。如果需要在子类内部访问某些基类成员,应将其定义为 protected。
总结访问规则:父类其他成员在子类的访问方式取决于 Min(成员在父类的访问限定符,继承方式)。实践中通常使用 public 继承,因为 class 默认继承方式是 private,而 struct 默认是 public。
用继承实现栈容器
之前我们可能用过适配器模式,这里展示如何用继承直接实现一个基于容器的栈。注意模板实例化和命名空间的作用。
如果在 push 函数中不指定类域,编译器会向上查找。由于 vector 是基类模板,直接调用 push_back(x) 可能会报错,因为编译器不知道 push_back 属于哪个类型。此时需要显式指定类域。
#include <vector>
using std;
Keda {
< >
: std::vector<T> {
:
{
vector<T>::(x);
}
{
vector<T>::();
}
{
vector<T>::();
}
{
vector<T>::();
}
};
}
{
Keda::stack<> st;
st.();
st.();
(!st.()) {
cout << st.() << ;
st.();
}
;
}


