C++继承详解(上):继承规则、父子类转换与作用域隐藏

继承的定义

什么是继承?直接看下面一段代码:

cpp 复制代码
class Person
{
public:
    void identity()
    {
        cout << _name << endl;
    }

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

class Student : public Person
{
protected:
    int _stuid;
};

class Teacher : public Person
{
protected:
    string _title;
};

person类中有很多属性是student与teacher共有的,为了减少代码的冗余重复,便有了继承,说白了就是你有的东西我也有但是我不想写,继承你的就行了。

始终把握一点:继承的父类也叫基类是地基,子类也叫派生类就是上面的楼房

如下图:

上左这个地基图很重要,是继承所有知识点的来源。

上面展示的继承类型为public 继承,也叫公有继承,继承当然有私有private,保护protect,公有public三种,继承类型不同其成员继承规则也不同,但是只需要看懂以下公式:

派生类中的访问权限 = Min(基类成员权限, 继承方式)

也就是如果是公有继承,但是父类是私有成员,那么父类的私有成员在子类中的权限是啥?根据这个公式也就是min(私有,公有)按照这个公式,应该是私有权限。

顺便提一下,struct默认是公有继承,而class默认是private继承。

继承类模版

cpp 复制代码
template<class T>
class stack : public std::vector<T>
{
public:
    void push(const T& x)
    {
        vector<T>::push_back(x);
    }
};

如果基类本身是一个类模板,派生类里访问基类成员时有时需要显式指定基类作用域。这是因为模板按需实例化,直接写 push_back(x) 可能找不到。

子类与父类之间的转换

cpp 复制代码
Student st;

Person* p1 = &st;
Person& p2 = st;
Person p3 = st;

前面2个都没有创建新的对象,因为st中本身就有地基,而地基就是person,但是最后一个会出现切片现象,也就是只将子类中包含父类的部分移植给对方,剩下的不要,如下:

bash 复制代码
Student st
┌────────────────────┐
│ Person 部分        │ ─────→ Person p3
├────────────────────┤
│ Student部分        │
│ _No                │ ← 被切掉
└────────────────────┘

但是父类不能直接给子类,这是显而易见的,person里面没有st需要的student部分。

但父类指针为什么可以强转回子类?

因为父类指针也可能指向的本身就是子类,所以C++为了防止误判,放开了这一权限,如下:

cpp 复制代码
Student st;

Person* p = &st;

Student* ps = static_cast<Student*>(p);

基类指针或引用可以强制转换成派生类指针或引用,但只有当它实际上指向派生类对象时才安全;如果基类是多态类型,还可以使用 dynamic_cast 做运行时识别。(等到多态再讲)

父类与子类的作用域

先看代码:

cpp 复制代码
class Person
{
protected:
    int _num = 111;
};

class Student : public Person
{
protected:
    int _num = 999;
};

int main(){
    Student s;
    std::cout<<s._num<<std::endl;
}
    

基类和派生类拥有独立作用域;如果出现同名成员,派生类成员会屏蔽基类同名成员的直接访问,这叫**"隐藏"**。

如果直接打印_num,一定优先打印子类的999。

如果想获取父类的_num,则需要制定类域:

cpp 复制代码
Person::_num

因为子类对象始终是如下这种结构:

cpp 复制代码
Student st
┌────────────────────────┐
│ Person::_num = 111     │
├────────────────────────┤
│ Student::_num = 999    │
└────────────────────────┘

但是隐藏和重载需要分清楚隐藏通常是不同类域下的,而重载通常是相同类域下的。

相关推荐
skr爱码士12 分钟前
15_国际化和本地化:tr()、ts 文件、QM 文件、多语言切换
c++·qt·ui·客户端
汉克老师36 分钟前
CSP-J 初赛(以满分为目标):第二十一课 《树与二叉树基础—— 一棵树,为什么会成为计算机最重要的数据结构之一?》
c++·csp-j·小学生·学c++编程
别动我齐刘海1 小时前
从0到1独立搭建机器人软件系统
c++·人工智能·神经网络·opencv·目标检测·机器学习·机器人
dear_bi_MyOnly1 小时前
数组字符串深度解析:从入门到卡牌实战
开发语言·c++·学习
小欣加油2 小时前
Leetcode2058 找出临界点之间的最小和最大距离
数据结构·c++·算法·leetcode·职场和发展
王老师青少年编程2 小时前
2026年山东省小学组【信息学体验营】复赛真题及题解T2:小兔子爬楼梯
c++·真题·山东省·csp·信奥赛·复赛·信息学体验营
Yfhonier2 小时前
6441. 特别的除法
c++·算法
OPEN-F2 小时前
C++17新特性精讲:结构化绑定、if constexpr与实用类型
开发语言·c++
OPEN-F2 小时前
C++并发编程:线程与互斥锁
开发语言·c++