C++ 基础知识 五 ( 来看来看 面向对象的继承 上篇 )

这篇具有很好参考价值的文章主要介绍了C++ 基础知识 五 ( 来看来看 面向对象的继承 上篇 )。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、简介

1 什么是 C++ 继承

C++ 继承是指派生类(子类)从基类(父类)继承属性和行为的过程。我们可以创建一个新的类,该类可以继承另一个类的数据属性和方法。

// 定义一个父类 Person
class Person {
public:
    string name;
    int age;
    string gender;
    void eat() {
        cout << name << " is eating. \n";
    }
};

// 定义一个子类 Student 继承父类 Person 
class Student : public Person {
public:
    string school;
    void study() {
        cout << name << " is studying at " << school << ". \n";
    }
};

在上述代码中,我们定义了一个父类 Person 与一个子类 Student。Student 类继承了 Person 类的属性和方法,包括 name、age、gender 和 eat() 函数。

2 继承的目的和作用

继承的主要目的是代码重用:我们可以重用现有的代码,避免重复编写相同的代码,从而提高生产效率。此外,继承还使得代码更易于管理和维护,因为我们可以通过继承将代码组织成层次结构。

// 使用继承创建 Student 对象
Student myStudent;
myStudent.name = "Tom";
myStudent.age = 18;
myStudent.gender = "Male";
myStudent.school = "ABC University";

myStudent.eat();   // 输出 "Tom is eating."
myStudent.study(); // 输出 "Tom is studying at ABC University."

二、定义

继承是面向对象编程语言中一种非常常见的概念。继承可以让类之间实现代码重用,使得程序更加易于扩展和维护。在 C++ 中可以使用派生类和基类来实现继承。

1 派生类和基类的定义

派生类是指从一个或多个基类中派生出来的类。基类是指在一个类继承另一个类的语法中被继承的那个类。在 C++ 中,我们可以通过如下语法定义一个派生类:

class DerivedClass : access-specifier BaseClass {
public:
    // DerivedClass 的公有成员
protected:
    // DerivedClass 的保护成员
private:
    // DerivedClass 的私有成员
};

在上述代码中DerivedClass是我们新创建的类的名称,access-specifier 可以是 public、protected、或 private。BaseClass 是我们想要从中继承属性和方法的类,我们可以在 access-specifier 后面指定 BaseClass 的访问类型。

代码示例:
定义一个派生类 DerivedPerson,从基类 Person 继承属性和方法 :

#include <iostream>
#include <string>
using namespace std;

class Person {
public:
    string name;
    int age;
    void eat() {
        cout << name << " is eating.\n";
    }
};

class DerivedPerson : public Person {
public:
    void work() {
        cout << name << " is working.\n";
    }
};

int main() {
    DerivedPerson p;
    p.name = "John";
    p.age = 30;
    p.eat(); // 输出 "John is eating."
    p.work(); // 输出 "John is working."
    return 0;
}

2 公有继承和私有继承

C++ 中有三种类型的继承:公有继承、保护继承和私有继承。
公有继承是最常用的继承类型之一。在公有继承中派生类获得了基类的公有成员和保护成员,但是基类的私有成员不会被派生类直接访问。

公有继承的用法 示例:
代码定义一个基类 Base 和一个派生类 Derived
在Derived中使用公有继承来继承 Base类的属性和方法。在 main() 函数中创建一个Derived对象d,然后调用 set() 和 print() 函数来设置和获取成员变量 x 的值。需要注意的是此处通过派生类的对象访问了基类的公有成员 x 和 print()

#include <iostream>
using namespace std;

class Base {
public:
    int x;
    void print() {
        cout << "Base class: x = " << x << "\n";
    }
};

class Derived : public Base {
public:
    void set(int n) {
        x = n;
    }
};

int main() {
    Derived d;
    d.set(10);
    d.print(); // 输出 "Base class: x = 10"
    return 0;
}

除了公有继承C++ 中还有保护继承和私有继承。
在保护继承中,基类的公有成员和保护成员都成为了派生类的保护成员。
在私有继承中,基类的公有成员和保护成员都成为了派生类的私有成员。
挑选合适的继承类型对于代码的设计非常重要,在实际编码中需要仔细考虑。

三、访问控制

1 派生类对基类成员的访问权限

在C++中如果一个类派生自另一个类,则派生类可以继承基类的成员变量和成员函数。在继承过程中访问权限是非常重要的一个问题。
有三种访问权限:public、protected 和 private。当一个类派生自另一个类时继承的访问权限可以通过下列三种方式指定:

  • public 继承:基类的 public 成员在派生类中保持 public 属性,基类的 protected 成员在派生类中保持 protected 属性,基类的 private 成员在派生类中不可访问。
  • protected 继承:基类的 public 和 protected 成员在派生类中都被保护起来,不能被外部直接访问。这种方式很少使用,一般只有在继承链比较复杂的时候才使用。
  • private 继承:基类的 public 和 protected 成员在派生类中均变为 private 属性,不能被外部直接访问。这种方式也比较少使用,一般只有在需要从多个类中继承同一个基类的时候才使用。

下面是一个使用 public 继承的例子,演示了派生类对基类成员的访问权限:

在代码中Derived类继承了Base类的公有成员变量 x 和成员函数 print(),以及保护成员变量y
在Derived类的成员函数中可以访问这些成员但是不能直接访问 Base 类的私有成员z

#include <iostream>
using namespace std;

class Base {
public:
    int x;
    void print() {
        cout << "Base class: x = " << x << "\n";
    }
protected:
    int y;
private:
    int z;
};

class Derived : public Base {
public:
    void set(int a, int b, int c) {
        x = a;
        y = b;
        // z = c; 无法访问基类的私有成员
    }
    void print1() {
        cout << "Derived class: x = " << x << "\n";
    }
    void print2() {
        cout << "Derived class: y = " << y << "\n";
    }
    // void print3() { cout << "Derived class: z = " << z << "\n"; } 无法访问基类的私有成员
};

int main() {
    Derived d;
    d.set(1, 2, 3);
    d.print(); // 输出 "Base class: x = 1"
    // cout << d.y; 无法访问基类的保护成员
    d.print1(); // 输出 "Derived class: x = 1"
    d.print2(); // 输出 "Derived class: y = 2"
    return 0;
}

2 如何控制访问权限

在C++中可以使用访问修饰符来控制类的成员的访问权限。访问修饰符可以放到类的定义中的任何位置,而且多次使用访问修饰符是合法的,因为后面的修饰符会覆盖之前的修饰符。

  • public:公有修饰符可以从类的任何地方访问公有成员也可以从派生类的任何地方访问公有成员。
  • protected:保护修饰符只能从类的内部或派生类的内部访问保护成员外部不能访问。
  • private:私有修饰符只能从类的内部访问私有成员派生类的内部不能访问。

下面是一个使用访问修饰符的例子,演示了如何控制成员的访问权限:

在代码中定义了MyClass类和MyDerivedClass类。
在MyClass中使用 public、protected 和 private 三种访问修饰符定义了三个不同的成员变量。在MyDerivedClass中从MyClass中继承了各种成员,并在成员函数中分别访问了这些成员。需要注意的是,在派生类中可以访问基类的 public 和 protected 成员,但是不能访问基类的 private 成员。

#include <iostream>
using namespace std;

class MyClass {
public:
    int a;          // 公有成员变量
protected:
    int b;          // 保护成员变量
private:
    int c;          // 私有成员变量

public:
    void set(int x, int y, int z) {
        a = x;
        b = y;
        c = z;
    }
    void print() {
        cout << "a = " << a << ", b = " << b << ", c = " << c << "\n";
    }
};

class MyDerivedClass : public MyClass {
public:
    void setDerived(int x, int y, int z) {
        // a 和 b 都是 public 和 protected 成员,可以直接访问
        a = x;
        b = y;
        // c 是 private 成员,无法直接访问
        //c = z;
    }
    void printDerived() {
        // a 是 public 成员,可以直接访问
        cout << "a = " << a << "\n";
        // b 是 protected 成员,在派生类的内部可以访问
        cout << "b = " << b << "\n";
        // c 是 private 成员,无法直接访问
        //cout << "c = " << c << "\n";
    }
};

int main() {
    MyClass obj;
    obj.set(1, 2, 3);
    obj.print();

    MyDerivedClass obj2;
    obj2.setDerived(4, 5, 6);
    obj2.printDerived();

    return 0;
}

四、虚函数继承

1 继承中的虚函数机制

在C++ 中如果一个类有虚函数,那么当这个类被继承时在派生类中也会有虚函数表 (V-Table)。当使用基类指针或引用指向一个派生类对象时会根据虚函数表找到正确的虚函数。这种机制被称为动态联编,也就是运行时多态或后期绑定。

代码中定义了一个Base 类和一个 Derived 类。在 Base 类中有一个虚函数 print()
Derived类继承了Base 类并重写了 print() 函数。在 main() 函数中创建了 Derived 类的对象 d并使用 Base 类的指针 b_ptr 指向它,然后调用 print() 函数输出了 "Derived"

#include <iostream>
using namespace std;

class Base {
public:
    virtual void print() {
        cout << "Base\n";
    }
};

class Derived : public Base {
public:
    void print() override {
        cout << "Derived\n";
    }
};

int main() {
    Derived d;
    Base* b_ptr = &d;
    b_ptr->print(); // Derived
    return 0;
}

2 在派生类中重写虚函数

派生类可以通过重写基类中的虚函数来改变其行为

在代码中使用了上一个示例中的 Base 类和 Derived 类并在 Derived 类中重写了print() 函数
main() 函数中通过Base类和Derived类的指针调用 print() 函数。当使用 Base 类指针 b_ptr2 指向 Base 类的对象时,调用的是 Base 类中的 print() 函数,输出了 "Base"。当使用 Base 类指针 b_ptr 指向 Derived 类的对象时,调用的是 Derived 类中的 print() 函数,输出了 "Derived"

#include <iostream>
using namespace std;

class Base {
public:
    virtual void print() {
        cout << "Base\n";
    }
};

class Derived : public Base {
public:
    void print() override {
        cout << "Derived\n";
    }
};

int main() {
    Derived d;
    Base* b_ptr = &d;
    b_ptr->print(); // Derived

    Base base;
    Base* b_ptr2 = &base;
    b_ptr2->print(); // Base
    return 0;
}

五、多重继承

在C++ 中一个派生类可以同时继承多个基类,这种继承方式被称为多重继承。

1 语法实现

多重继承是指一个派生类可以同时继承多个基类,其中每个基类可以有自己的成员函数和成员变量。一个类可以声明对多个基类的继承方式语法如下:

class Derived : access-specifier Base1, access-specifier Base2, ... {
    // Derived class members and functions
};

其中,access-specifier 指定了基类成员在派生类中的访问权限,可以用 publicprotectedprivate 指定。如果没有指定,则默认为 private

2 派生类和基类成员的访问规则

在多继承中派生类对象同时包含多个基类对象的数据成员和成员函数。根据继承方式的不同,基类成员的访问规则也会有所不同。

2.1 共同基类的继承

如果多个基类都派生自同一个基类,那么这个基类的数据成员和成员函数只会在派生类中出现一次。在访问这个基类的成员时,将使用这个共同基类的数据成员和成员函数。

代码示例:
在代码中创建了 AnimalMammalDogCatPersianCat 类。
MammalCat 都是直接继承自 AnimalDogPersianCat 分别是直接继承自 MammalCat。在 PersianCat 类中同时使用了 CatMammal 作为基类

main() 函数中创建了一个 PersianCat 对象,并调用了它的 show_info() 函数。在这个函数中调用了 AnimalMammalCat 这三个基类的一些成员函数,它们分别是在不同的层级中定义的。由于它们都继承自共同的基类 Animal,因此在访问这个基类的成员时,它们都使用同一个 Animal 对象的数据成员和成员函数。在控制台输出中可以看到不同的动物都调用了正确的成员函数

#include <iostream>
using namespace std;

class Animal {
public:
    void eat() {
        cout << "Animal is eating\n";
    }
};

class Mammal : public Animal {
public:
    void run() {
        cout << "Mammal is running\n";
    }
};

class Dog : public Mammal {
public:
    void bark() {
        cout << "Dog is barking\n";
    }
};

class Cat : public Animal {
public:
    void meow() {
        cout << "Cat is meowing\n";
    }
};

class PersianCat : public Cat, public Mammal {
public:
    void show_info() {
        eat(); // 使用Animal中的eat()函数
        run(); // 使用Mammal中的run()函数
        meow(); // 使用Cat中的meow()函数
        cout << "A Persian cat\n";
    }
};

int main() {
    PersianCat persian_cat;
    persian_cat.show_info(); 
    return 0;
}

2.2 不同基类的继承

当派生类继承了多个不同的基类时,会出现基类成员的二义性,需要使用作用域解析运算符来解决。

代码示例:
代码中创建了 ABC 类。C 类同时继承自 AB。在 C 类的 show_info() 函数中,我们使用作用域解析运算符 :: 来指定调用哪个基类的 func() 函数。在 main() 函数中,我们创建了 C 对象,并调用了它的 show_info() 函数。在控制台输出中可以看到它分别调用了两个基类的 func() 函数。

#include <iostream>
using namespace std;

class A {
public:
    void func() {
        cout << "class A" << endl;
    }
};

class B {
public:
    void func() {
        cout << "class B" << endl;
    }
};

class C : public A, public B {
public:
    void show_info() {
        A::func();
        B::func();
    }
};

int main() {
    C c;
    c.show_info(); // class A \n class B
    return 0;
}

六、小结回顾

C++中访问控制通过 public、protected 和 private 关键字来实现。public 表示公开的可以被任何地方访问。protected 表示受保护的只有本类和其子类可以访问。private 表示私有的只有本类可以访问。

C++中的虚函数继承可以实现多态性。子类可以重载父类的虚函数,并且子类的对象可以看做是父类的对象从而实现多态性。

多重继承是 C++ 中的一个重要特性允许一个类从多个基类中继承属性和方法。在实现上如果一个类同时继承了多个基类就可能出现菱形继承问题。为了避免这种问题C++ 提供了虚继承来解决。虚继承可以实现让派生类只继承一份基类的数据成员,从而避免数据冗余和数据不一致的问题。文章来源地址https://www.toymoban.com/news/detail-437123.html

到了这里,关于C++ 基础知识 五 ( 来看来看 面向对象的继承 上篇 )的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python 面向对象的概念及使用方法~(基础小知识)

    编程语言中,一般有两种编程思维,面向过程和面向对象。 面向过程,看重的是解决问题的过程。 这好比我们解决日常生活问题差不多,分析解决问题的步骤,然后一步一步的解决。 而面向对象是一种抽象,抽象是指用分类的眼光去看世界的一种方法。 Python 就是一门面向

    2024年02月06日
    浏览(49)
  • [ XJTUSE ]JAVA语言基础知识——第一章 面向对象程序设计思想

    类描述了一组有相同 特性 (属性)和相同 行为 (方法)的对象,类和对象是面向对象思想的两个核心概念 · 人类是一种类,每一个具体的人则是这个类的对象 用面向对象程序来模拟真实世界 发现并创建类 发现类的特征 发现类的行为 在面向对象程序中,对象的特征由各种

    2023年04月13日
    浏览(82)
  • Java 学习路线:基础知识、数据类型、条件语句、函数、循环、异常处理、数据结构、面向对象编程、包、文件和 API

    Java 是一种由 Sun Microsystems 于 1995 年首次发布的编程语言和计算平台。Java 是一种通用的、基于类的、面向对象的编程语言,旨在减少实现依赖性。它是一个应用程序开发的计算平台。Java 快速、安全、可靠,因此在笔记本电脑、数据中心、游戏机、科学超级计算机、手机等领

    2024年03月24日
    浏览(87)
  • C++类和对象基础知识详解

    1.一切皆是对象。如下图: ·女人是一个对象 ·鞋子是一个对象 ·包包是一个对象 ·衣服是一个对象 ·裤子是一个对象 ·手链是一个对象 … 这里人这个对象,由鞋子、包包、衣服、 裤子、手链等对象组成。 3.每个对象都有: a)数据(描述对象的属性) b)函数(行为操作代码

    2023年04月12日
    浏览(43)
  • 【C++】继承基础知识及简单应用,使用reportSingleClassLayout(在Visual Studio开发人员命令提示窗口)查看派生类详细信息

    author:Carlton tag:C++ topic:【C++】继承基础知识及简单应用,使用reportSingleClassLayout(在Visual Studio开发人员命令提示窗口)查看派生类详细信息 website:黑马程序员C++ date:2023年7月22日 目录 概要 继承规则 对象模型 构造析构顺序 同名与静态同名成员 多继承 菱形继承 VS开发人

    2024年02月16日
    浏览(51)
  • Elasticsearch的基础知识和架构设计,以及一些常用的功能——面向对象编程和数据结构的高级应用场景,以及相应的代码实现方法和工具

    作者:禅与计算机程序设计艺术 2019年,Elasticsearch正式发布了7.0版本。在这个版本更新中,新增了许多新特性和功能,包括全文搜索、分类聚合、分析器、图形化数据可视化等。无论对于企业或个人来说,都意味着更好的应用场景。但是,掌握Elasticsearch并非易事,需要不断学

    2024年02月07日
    浏览(50)
  • 【C++系列P3】‘类与对象‘-三部曲——[基础知识](1/3)

    前言 大家好吖,欢迎来到 YY 滴 C++系列 ,热烈欢迎! 【 \\\'类与对象\\\'-三部曲 】的大纲主要内容如下 : 如标题所示,本章是【 \\\'类与对象\\\'-三部曲 】三章中的第 一 章节—— 基础知识章节 ,主要内容如下: 目录 一. This指针 1.编译器对This指针的处理本质——不允许修改this,但

    2024年02月11日
    浏览(45)
  • 【C++面向对象】8. 继承

    继承允许我们依据一个类来定义另一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了 重用代码功能 和 提高执行时间 的效果。 当创建一个类时,我们不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已

    2024年02月08日
    浏览(51)
  • C++ 面向对象(2)——继承

    面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行效率的效果。 当创建一个类时,您不需要重新编写新的数据成员和成员函数,只需指定新建的类

    2024年02月10日
    浏览(44)
  • C++ 面向对象三大特性——继承

    ✅1主页:我的代码爱吃辣 📃2知识讲解:C++ 继承 ☂️3开发环境:Visual Studio 2022 💬4前言:面向对象三大特性的,封装,继承,多态,今天我们研究研究 C++的继承 。 目录 一.继承的概念及定义 1.继承的概念  2.继承的定义 二. 继承关系和访问限定符  三.基类和派生类对象赋

    2024年02月12日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包