【C++】面向对象编程的三大特性:深入解析继承机制(一)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 【C++】面向对象编程的三大特性:深入解析继承机制

一、前文

面向对象编程的三大特性:封装、继承和多态。

  1. 封装通过将数据和方法封装在对象中,提高了数据的安全性和代码的可维护性。
  2. 继承允许新类从现有类继承属性和方法,实现代码复用和扩展。
  3. 多态则通过统一的接口实现不同的行为,提高了代码的灵活性和扩展性。

封装:

  1. 数据和方法放到一起,把想给访问定义成公有,不想给你访问定义成私有和保护
  2. 一个类型放到另一个类型里面,通过typedef成员函数调整,封装另一个全新的类型相当于武器库

二、继承

2.1 继承概念

  • 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。
  • 它允许一个类(称为子类或派生类)从另一个类(称为父类或基类)继承属性和方法
  • 每个派生类对象都是一个特殊的基类对象,派生类在基类的基础上进行扩展,增加新功能
  • 继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。
  • 以前我们接触的复用都是函数复用,继承是类设计层次的复用
using namespace std;
class Person
{
    public:
    void Print()
    {
        cout << "name:" << _name << endl;
        cout << "age:" << _age << endl;
    }
    private:
    string _name = "peter";//名字
    int _age = 18;//年龄
};
class Student : public Person
{
    protected:
    int _stuid;//学号
};
class Teacher : public Person
{
    protected:
    int jobid;//工号
};
int main()
{
    Student s;
    Teacher t;
    s.Print();
    t.Print();
    return 0;
}

从代码中可以看出Person是父类或基类,Student是子类或派生类

2.2 继承关系和访问限定符

2.3 继承基类成员访问方式间变化

注意】:圈出来的是实践中最常见的设计方式,主要了解这部分。

2.4 基类的private成员

基类private成员在派生类中无论以什么方式继承都是不可见的,这里的不可见是指基类的私有成员还是被继承到了派生类中,但是语法上限制派生类对象不管在类里面还是在类外面都是不能去访问

class Person
{
    public:
    void Print()
    {
        cout << "name:" << _name << endl;
        cout << "age:" << _age << endl;
    }
    protected:
    string _name = "peter";
    private:
    int _age = 18;
};
class Student : public Person
{
    public:
    void func()
    {
        cout << _name << endl;
        cout << _age << endl;
    }
    protected:
    int _stuid;
};

按照上面的意思,Student继承了Person属性和方法,但是由于_age是属于私有成员是不可见且不能被访问。

2.4.1 公共接口间接使用基类的私有变量

class Student : public Person
{
    public:
    void func()
    {
        //间接的使用
        Print();
    }
    protected:
    int _stuid;
};

由于基类private成员在派生类中式不能被访问的,如果基类成员不想在类外直接被访问,但是需要在派生类中能访问。这样子可以将基类private成员定义为protected成员,可以看出来保护成员限定符是因继承才出现的

思考:

  • 类可以使用关键字class或者struct,他们只是默认的继承方式不同,为什么不使用struct呢?

解释:

  • struct默认继承方式和访问限定符都是公有的
  • class默认继承方式和访问限定符都是私有的
  • 最好函数显式写出继承方式,偷偷摸摸的不好!

2.5小结

  • 基类的私有成员在子类都是不可见。基类的其他成员在访问方式(取最小的权限)== Min(成员在基类的访问限定符、继承方式)public > prrotected > private
  • 在实际中一般常用的是public继承,而不是protected/private继承,也不提倡使用protected/private继承,因为protected/private继承下来的成员都是只能在派生类的类里面使用,实际中扩展维护性不强

2.6 基类和派生类对象赋值转换

2.6.1 派生类赋值基类

每个派生类对象都是一个特殊的基类对象,派生类在基类的基础上进行扩展,增加新功能

class Person
{
    protected:
    string _name;
    string _sex;
    int _age;
};
class Student : public Person
{
    public:
    int _No; //学号
};

派生类对象可以赋值基类的对象/基类的指针/基类的引用。这里有个形象的说法叫切片或者切割。(将派生类中父类那部分切来赋值过去)。

int main()
{
    Student sobj;
  //子类对象可以赋值给父类对象
    Person pobj = sobj;
    //子类对象可以赋值给父类指针
    Person* pp = &sobj;
    //子类对象可以赋值给父类引用
    Person& rp = sobj;
}

2.6.2 基类对象不能赋值给派生类对象(建立在public继承)

int main()
{
    Student sobj;
    Person pobj = sobj;
    Person* pp = &sobj;
    sobj = pobj;
}

基类是不能直接赋值给派生类,因为可能派生类包含了基类没有的额外属性和方式,而且基类是不具备这些属性和方式,对此不能直接赋值。

2.6.3 强制基类赋值派生类

基类的指针或者引用可用通过强制类型转化赋值给派生类的指针或者引用。但是必须是基类的指针是指向派生类对象时才是安全的。

int main()
{
    Student sobj;
    Person pobj = sobj;
    Person* pp = &sobj;
    1.0
    //pp存放这子类实例的地址,再进行强转
    pp = &sobj; 
    // 这种情况转换时可以的。
    Student* ps1 = (Student*)pp; 
    ps1->_No = 10;
  
    2.0
    //pp存放父类实例的地址
    pp = &pobj;
    // 这种情况转换时虽然可以,但是会存在越界访问的问题
    Student* ps2 = (Student*)pp; 
    ps2->_No = 10;
}

注意:

  • 以上提前需要满足是公有继承
  • 切割/切片是赋值兼容,编译器进行特殊处理,不产生临时对象,将子拷贝给父。内置类型值拷贝,自定义类型调用拷贝构造。


【C++】面向对象编程的三大特性:深入解析继承机制(二)https://developer.aliyun.com/article/1617389

相关文章
|
2天前
|
编译器 程序员 定位技术
C++ 20新特性之Concepts
在C++ 20之前,我们在编写泛型代码时,模板参数的约束往往通过复杂的SFINAE(Substitution Failure Is Not An Error)策略或繁琐的Traits类来实现。这不仅难以阅读,也非常容易出错,导致很多程序员在提及泛型编程时,总是心有余悸、脊背发凉。 在没有引入Concepts之前,我们只能依靠经验和技巧来解读编译器给出的错误信息,很容易陷入“类型迷路”。这就好比在没有GPS导航的年代,我们依靠复杂的地图和模糊的方向指示去一个陌生的地点,很容易迷路。而Concepts的引入,就像是给C++的模板系统安装了一个GPS导航仪
77 59
|
5天前
|
安全 编译器 PHP
PHP 7新特性深度解析与实践
【10月更文挑战第7天】在这篇文章中,我们将探索PHP 7带来的新特性和改进,以及如何利用这些新工具来提升你的代码效率。从性能优化到语法简化,再到错误处理的改进,本文将带你深入了解PHP 7的核心变化,并通过实际代码示例展示如何将这些新特性应用到日常开发中。无论你是PHP新手还是资深开发者,这篇文章都将为你提供有价值的见解和技巧。
17 6
|
6天前
|
Web App开发 前端开发 测试技术
Selenium 4新特性解析:关联定位器及其他创新功能
【10月更文挑战第6天】Selenium 是一个强大的自动化测试工具,广泛用于Web应用程序的测试。随着Selenium 4的发布,它引入了许多新特性和改进,使得编写和维护自动化脚本变得更加容易。本文将深入探讨Selenium 4的一些关键新特性,特别是关联定位器(Relative Locators),以及其他一些重要的创新功能。
36 2
|
7天前
|
自动驾驶 安全 物联网
|
14天前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(三)
【C++】面向对象编程的三大特性:深入解析多态机制
|
14天前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(二)
【C++】面向对象编程的三大特性:深入解析多态机制
|
14天前
|
编译器 C++
【C++】面向对象编程的三大特性:深入解析多态机制(一)
【C++】面向对象编程的三大特性:深入解析多态机制
|
14天前
|
存储 安全 编译器
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值(一)
【C++】C++特性揭秘:引用与内联函数 | auto关键字与for循环 | 指针空值
|
14天前
|
存储 编译器 C++
【C++】面向对象编程的三大特性:深入解析继承机制(三)
【C++】面向对象编程的三大特性:深入解析继承机制
|
14天前
|
编译器 C++
【C++】面向对象编程的三大特性:深入解析继承机制(二)
【C++】面向对象编程的三大特性:深入解析继承机制

热门文章

最新文章

推荐镜像

更多