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

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【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

相关文章
|
1月前
|
编译器 C# 开发者
C# 9.0 新特性解析
C# 9.0 是微软在2020年11月随.NET 5.0发布的重大更新,带来了一系列新特性和改进,如记录类型、初始化器增强、顶级语句、模式匹配增强、目标类型的新表达式、属性模式和空值处理操作符等,旨在提升开发效率和代码可读性。本文将详细介绍这些新特性,并提供代码示例和常见问题解答。
46 7
C# 9.0 新特性解析
|
1月前
|
自然语言处理 编译器 Linux
|
25天前
|
编译器 PHP 开发者
PHP 8新特性解析与实战应用####
随着PHP 8的发布,这一经典编程语言迎来了诸多令人瞩目的新特性和性能优化。本文将深入探讨PHP 8中的几个关键新功能,包括命名参数、JIT编译器、新的字符串处理函数以及错误处理改进等。通过实际代码示例,展示如何在现有项目中有效利用这些新特性来提升代码的可读性、维护性和执行效率。无论你是PHP新手还是经验丰富的开发者,本文都将为你提供实用的技术洞察和最佳实践指导。 ####
28 1
|
26天前
|
数据安全/隐私保护 iOS开发 开发者
iOS 14隐私保护新特性深度解析####
随着数字时代的到来,隐私保护已成为全球用户最为关注的问题之一。苹果在最新的iOS 14系统中引入了一系列创新功能,旨在增强用户的隐私和数据安全。本文将深入探讨iOS 14中的几大隐私保护新特性,包括App跟踪透明度、剪贴板访问通知和智能防追踪功能,分析这些功能如何提升用户隐私保护,并评估它们对开发者和用户体验的影响。 ####
|
1月前
|
设计模式 安全 数据库连接
【C++11】包装器:深入解析与实现技巧
本文深入探讨了C++中包装器的定义、实现方式及其应用。包装器通过封装底层细节,提供更简洁、易用的接口,常用于资源管理、接口封装和类型安全。文章详细介绍了使用RAII、智能指针、模板等技术实现包装器的方法,并通过多个案例分析展示了其在实际开发中的应用。最后,讨论了性能优化策略,帮助开发者编写高效、可靠的C++代码。
35 2
|
1月前
|
安全 编译器 C++
【C++11】新特性
`C++11`是2011年发布的`C++`重要版本,引入了约140个新特性和600个缺陷修复。其中,列表初始化(List Initialization)提供了一种更统一、更灵活和更安全的初始化方式,支持内置类型和满足特定条件的自定义类型。此外,`C++11`还引入了`auto`关键字用于自动类型推导,简化了复杂类型的声明,提高了代码的可读性和可维护性。`decltype`则用于根据表达式推导类型,增强了编译时类型检查的能力,特别适用于模板和泛型编程。
24 2
|
8天前
|
安全 编译器 C++
C++ `noexcept` 关键字的深入解析
`noexcept` 关键字在 C++ 中用于指示函数不会抛出异常,有助于编译器优化和提高程序的可靠性。它可以减少代码大小、提高执行效率,并增强程序的稳定性和可预测性。`noexcept` 还可以影响函数重载和模板特化的决策。使用时需谨慎,确保函数确实不会抛出异常,否则可能导致程序崩溃。通过合理使用 `noexcept`,开发者可以编写出更高效、更可靠的 C++ 代码。
14 0
|
8天前
|
存储 程序员 C++
深入解析C++中的函数指针与`typedef`的妙用
本文深入解析了C++中的函数指针及其与`typedef`的结合使用。通过图示和代码示例,详细介绍了函数指针的基本概念、声明和使用方法,并展示了如何利用`typedef`简化复杂的函数指针声明,提升代码的可读性和可维护性。
34 0
|
1月前
|
PHP 开发者
PHP 7新特性深度解析
【10月更文挑战第40天】随着PHP 7的发布,这个广泛使用的语言带来了许多令人兴奋的新特性和性能改进。本文将深入探讨PHP 7的主要变化,包括类型声明、错误处理机制、性能优化等方面,帮助开发者更好地理解和应用这些新特性。
34 4
|
1月前
|
C# 开发者
C# 10.0 新特性解析
C# 10.0 在性能、可读性和开发效率方面进行了多项增强。本文介绍了文件范围的命名空间、记录结构体、只读结构体、局部函数的递归优化、改进的模式匹配和 lambda 表达式等新特性,并通过代码示例帮助理解这些特性。
36 2

推荐镜像

更多