一文带你学习C++中的派生机制

目录
  • 一、派生的类型
  • 二、派生的语法
  • 三、多重继承
  • 四、虚继承
  • 五、派生类和基类的关系
  • 六、总结

C++是一门面向对象的编程语言,其中的派生机制是其重要的面向对象特性之一。派生是建立在现有类的基础之上,创建一个新的类的过程。在新类中,可以利用父类中定义的变量和方法,并且可以添加新的成员变量和方法。

下面我们来详细地学习C++中的派生机制。

一、派生的类型

C++支持以下几种派生类型:

1.公有派生: 在公有派生中,派生类可以访问基类中的公有成员和受保护成员,但不能访问基类中的私有成员。公有派生通常用于向基类添加新的特征和行为。

示例代码如下:

class Base {
public:
    int public_var;
protected:
    int protected_var;
private:
    int private_var;
};

class Derived : public Base {
public:
    void setVar(int a, int b, int c)
    {
        public_var = a;  //公有成员可以在派生类中访问
        protected_var = b;  //受保护成员可以在派生类中访问
        // private_var = c;  //私有成员无法在派生类中访问
    }
};

2.保护派生: 在保护派生中,派生类可以访问基类中的公有成员和受保护成员,但不能访问基类中的私有成员。保护派生通常用于继承,即将基类的所有成员和方法都继承到派生类中。

示例代码如下:

class Base {
public:
    int public_var;
protected:
    int protected_var;
private:
    int private_var;
};

class Derived : protected Base {
public:
    void setVar(int a, int b, int c)
    {
        public_var = a;  //公有成员可以在派生类中访问
        protected_var = b;  //受保护成员可以在派生类中访问
        // private_var = c;  //私有成员无法在派生类中访问
    }
};

3.私有派生: 在私有派生中,派生类可以访问基类中的公有成员和受保护成员,但不能访问基类中的私有成员。私有派生通常用于“隐藏”继承,即对基类进行改进或扩展,但不公开基类的接口。

示例代码如下:

class Base {
public:
    int public_var;
protected:
    int protected_var;
private:
    int private_var;
};

class Derived : private Base {
public:
    void setVar(int a, int b, int c)
    {
        public_var = a;  //公有成员可以在派生类中访问
        protected_var = b;  //受保护成员可以在派生类中访问
        // private_var = c;  //私有成员无法在派生类中访问
    }
};

二、派生的语法

在C++中,派生的语法为:

class Derived_class : access_specifier Base_class {
    // 包含新成员和覆盖的函数等
};

其中,Derived_class 是基于 Base_class 的派生类。access_specifier 表示派生类型,可以是 public、protected 或 private。新的成员和覆盖的函数等是指在派生类中添加的成员和方法。

示例代码如下:

class Base {
public:
    void print() {
        std::cout << "Base" << std::endl;
    }
};

class Derived : public Base {
public:
    void print() {
        std::cout << "Derived" << std::endl;
    }
};

int main()
{
    Base b;
    Derived d;

    b.print(); //输出 Base
    d.print(); //输出 Derived

    return 0;
}

上述代码中,Base 类中定义了一个 print() 方法,输出 Base。Derived 类继承自 Base 类,并定义了一个同名的 print() 方法,输出 Derived。在 main 函数中,分别创建了 Base 类和 Derived 类的对象并分别调用了它们的 print() 方法。结果显示,派生类覆盖了其基类的同名方法。

三、多重继承

C++还支持多重继承,即一个派生类从多个基类派生而来。具体地,可以这样建立一个派生类:

class Derived : access_specifier Base1, access_specifier Base2, ... {
    // 包含新成员和覆盖的函数等
};

其中,Derived 是一个派生类,Base1、Base2 是两个基类,可以有多个基类。access_specifier 表示该基类在派生类中的访问权限,可以是 public、protected 或 private。

示例代码如下:

class Base1 {
public:
    void print1() {
        std::cout << "Base1" << std::endl;
    }
};

class Base2 {
public:
    void print2() {
        std::cout << "Base2" << std::endl;
    }
};

class Derived : public Base1, protected Base2 {
public:
    void print() {
        print1();
        //print2(); //private 成员不能在派生类之外的成员函数中访问
    }
};

int main()
{
    Derived d;
    d.print();

    return 0;
}

上述代码中,定义了两个基类 Base1 和 Base2,分别有各自的方法 print1() 和 print2()。派生类 Derived 继承自 Base1 和 Base2,由于 Base2 的访问权限设置为 protected,在 Derived 中,只有成员函数可以访问 Base2 中的成员。Derived 中定义的 print() 方法分别调用了 Base1 和 Base2 中的方法,结果显示,多重继承能够在派生类中同时使用多个基类的成员,并进行灵活的访问权限设置。

四、虚继承

当一个类同时从多个基类继承,而这些基类中又有共同的基类时,就会出现“二义性”的问题。为了解决这个问题,C++引入了虚继承机制。

虚继承使用关键字 virtual,它告诉编译器,在继承链中只保留一份共同的基类,从而避免了多次继承造成的冗余。另外,虚继承还规定了一个虚基类列表。虚基类列表中的类在继承链中只继承一次,并且会在最深层的派生类中进行初始化。

示例代码如下:

class Root {
public:
    int i;
};

class A : public virtual Root {
public:
    int j;
};

class B : public virtual Root {
public:
    int k;
};

class C : public A, public B {
public:
    void sum() {
        i = j + k;
    }
};

int main()
{
    C c;

    c.j = 10;
    c.k = 20;
    c.sum();

    std::cout << "Sum of j and k is " << c.i << std::endl;

    return 0;
}

上述代码中,定义了一个基类 Root,和两个继承了 Root 的派生类 A 和 B。类 C 同时从 A 和 B 继承,它将 A 和 B 中的 i 合并为一份,并且在最深层的派生类 C 中进行初始化。在 main 函数中,我们创建了类 C 的对象 c,并对它的成员变量 j 和 k 赋值,并通过 sum() 方法计算它们的和。

五、派生类和基类的关系

派生类和基类之间存在以下关系:

  • 派生类包含的成员都是派生类自己定义的,但它可以访问基类的公有成员和受保护成员,也可以使用基类中的方法。
  • 派生类的对象中包含了基类的对象,即派生类的对象中包含了基类对象的成员。
  • 派生类的对象可以被看作是基类的对象,即派生类的对象可以直接赋值给基类对象。

示例代码如下:

class Base {
public:
    int publicVar;
protected:
    int protectedVar;
private:
    int privateVar;
public:
    void print() {
        std::cout << "publicVar: " << publicVar << std::endl;
        std::cout << "protectedVar: " << protectedVar << std::endl;
        std::cout << "privateVar: " << privateVar << std::endl;
    }
};

class Derived : public Base {
public:
    int additionalVar;
public:
    void printAdditionalVar() {
        std::cout << "additionalVar: " << additionalVar << std::endl;
    }
};

int main()
{
    Derived derived;
    derived.publicVar = 1;
    //derived.protectedVar = 2;  //protected 成员不能直接在类外部访问
    derived.print();  //基类中的公有成员和受保护成员可以在派生类对象中访问
    derived.additionalVar = 3;
    derived.printAdditionalVar();  //派生类中的成员可以直接访问
    Base& base = derived;  //派生类的对象可以赋值给基类对象
    base.print();  //基类中的成员可以在基类对象中访问
    return 0;
}

上述代码中,定义了一个基类 Base 和一个派生类 Derived。在 main 函数中,我们首先创建了一个 Derived 的对象 derived,可以看到它可以访问由其基类 Base 中继承的成员变量和方法。同时,我们为 derived 对象中定义了一个 additionalVar 成员,并定义了一个打印 additionalVar 的方法。接着,我们将 derived 对象赋值给了一个 Base 类型的引用 base,并通过 base 访问了 Base 类中的成员变量和方法。结果显示了派生类和基类之间的关系。

六、总结

本文介绍了C++中的派生机制,包括公有派生、保护派生、私有派生、多重继承和虚继承等。同时,文章还介绍了派生类和基类之间的关系。理解并掌握派生机制,可以提高我们在C++编程中的应用技能。

到此这篇关于一文带你学习C++中的派生机制的文章就介绍到这了,更多相关C++派生机制内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 深入分析C++派生类中的保护成员继承

    protected 与 public 和 private 一样是用来声明成员的访问权限的.由protected声明的成员称为"受保护的成员",或简称"保护成员".从类的用户角度来看,保护成员等价于私有成员.但有一点与私有成员不同,保护成员可以被派生类的成员函数引用. 如果基类声明了私有成员,那么任何派生类都是不能访问它们的,若希望在派生类中能访问它们,应当把它们声明为保护成员.如果在一个类中声明了保护成员,就意味着该类可能要用作基类,在它的派生类中会访问这些成员.

  • C++的继承和派生你了解吗

    目录 继承的写法 继承实质与权限问题​ 总结 继承的写法 //父类 基类 class parent { }; //子类 派生类 //公有继承 class soon1:public parent { public: protected: }; //保护继承 class son2:protected parent { public: protected: }; //私有继承 class son3:private parent { public: protected: }; //继承和派生 //继承:

  • C++ 类的继承与派生实例详解

     C++ 类的继承与派生实例详解 继承性是面向对象程序设计最重要的特性之一,使软件有了可重用性,C++提供的类的继承机制. 继承与派生的概念 一个新类从已有的类那里获得已有的特性,这种现象称为类的继承.同样也可以说成已有的类派生出来了新的类.类A继承自类B也就是类B派生了类A.所以继承和派生的关系就像小学时把字句和被字句的造句一样.有了继承与派生后,就有了父类/基类与子类/派生类,C++中将类B称为父类/基类,将类A称为子类/派生类. 派生类的声明: #include <iostream> u

  • 代码讲解C++继承和派生

    继承是是指一个对象直接使用另一对象的属性和方法. 继承的作用: 1.描述客观事物的层次结构 2.分类的方法进行分析和描述 3.复杂的系统层次化,提高代码的重用性 4.增强语言功能,提高软件开发效益 继承分为单继承,多继承 1.单继承:class 派生类名:访问方式 基类名{ 派生类成员} 说明: 1.派生类名由用户自己命名 2.访问方式:公有.私有.保护 3.基类名必须是程序一个已有的类 4.冒号:告诉系统,派生类从那个基类派生 5.派生类成员为:新定义的成员 2.单继承之共有继承 3.单继承之

  • C++类的继承和派生及指针安全引用

    目录 一.继承和paisheng 1.继承和派生的基础概念 2.如何定义子类 3.吸收和改造父类成员.添加新成员 二.指针引用 1.指针和引用的异同 2.指针的安全隐患 一.继承和paisheng 1.继承和派生的基础概念 继承指从现有类获得其特性,派生指从已有类产生新的类.原有的类称为基类或父类,新生的类称为子类或派生类.当子类只有一个父类时称为单继承,当子类含有多个父类时称为多继承.如果基类A直接参与了派生类B的派生过程,那么A类称为直接基类:基类的基类称为间接基类. 2.如何定义子类 定义

  • 深入解析C++中派生类的构造函数

    基类的构造函数不能被继承,在声明派生类时,对继承过来的成员变量的初始化工作也要由派生类的构造函数来完成.所以在设计派生类的构造函数时,不仅要考虑派生类新增的成员变量,还要考虑基类的成员变量,要让它们都被初始化. 解决这个问题的思路是:在执行派生类的构造函数时,调用基类的构造函数. 下面的例子展示了如何在派生类的构造函数中调用基类的构造函数. #include<iostream> using namespace std; //基类 class People{ protected: char *n

  • 一文带你学习C++中的派生机制

    目录 一.派生的类型 二.派生的语法 三.多重继承 四.虚继承 五.派生类和基类的关系 六.总结 C++是一门面向对象的编程语言,其中的派生机制是其重要的面向对象特性之一.派生是建立在现有类的基础之上,创建一个新的类的过程.在新类中,可以利用父类中定义的变量和方法,并且可以添加新的成员变量和方法. 下面我们来详细地学习C++中的派生机制. 一.派生的类型 C++支持以下几种派生类型: 1.公有派生: 在公有派生中,派生类可以访问基类中的公有成员和受保护成员,但不能访问基类中的私有成员.公有派生通

  • 一文带你了解Java中的SPI机制

    目录 1: SPI机制简介 2: SPI原理 3: 使用场景 4: 源码论证 5: 实战 6: 优缺点 6.1 优点 6.2 缺点 1: SPI机制简介 SPI 全称是 Service Provider Interface,是一种 JDK 内置的动态加载实现扩展点的机制,通过 SPI 技术我们可以动态获取接口的实现类,不用自己来创建.这个不是什么特别的技术,只是 一种设计理念. 2: SPI原理 Java SPI 实际上是基于接口的编程+策略模式+配置文件组合实现的动态加载机制. 系统设计的各个

  • 一文带你了解Golang中interface的设计与实现

    目录 前言 接口是什么 iface 和 eface 结构体 _type 是什么 itab 是什么 生成的 itab 是怎么被使用的 itab 关键方法的实现 根据 interfacetype 和 _type 初始化 itab 接口断言过程总览(类型转换的关键) panicdottypeI 与 panicdottypeE iface 和 eface 里面的 data 是怎么来的 convT* 方法 Java 里面的小整数享元模式 总结 在上一篇文章<go interface 基本用法>中,我们了

  • 一文带你了解Golang中的并发性

    目录 什么是并发性,为什么它很重要 并发性与平行性 Goroutines, the worker Mortys Channels, the green portal 总结 并发是一个很酷的话题,一旦你掌握了它,就会成为一笔巨大的财富.说实话,我一开始很害怕写这篇文章,因为我自己直到最近才对并发性不太适应.我已经掌握了基础知识,所以我想帮助其他初学者学习Go的并发性.这是众多并发性教程中的第一篇,请继续关注更多的教程. 什么是并发性,为什么它很重要 并发是指在同一时间运行多个事物的能力.你的电脑有

  • 一文带你理解 Vue 中的生命周期

    目录 1.beforeCreate & created 2.beforeMount & mounted 3.beforeUpdate & updated 4.beforeDestroy & destroyed 5.activated & deactivated 前言: 每个 Vue 实例在被创建之前都要经过一系列的初始化过程.例如需要设置数据监听.编译模板.挂载实例到 DOM.在数据变化时更新 DOM 等.同时在这个过程中也会运行一些叫做生命周期钩子的函数,给予用户

  • 一文带你掌握Java8中Lambda表达式 函数式接口及方法构造器数组的引用

    目录 函数式接口概述 函数式接口示例 1.Runnable接口 2.自定义函数式接口 3.作为参数传递 Lambda 表达式 内置函数式接口 Lambda简述 Lambda语法 方法引用 构造器引用 数组引用 函数式接口概述 只包含一个抽象方法的接口,称为函数式接口. 可以通过 Lambda 表达式来创建该接口的对象. 可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口.同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口.

  • 一文带你了解Java中的ForkJoin

    目录 什么是ForkJoin? ForkJoinTask 任务 ForkJoinPool 线程池 工作窃取算法 构造方法 提交方法 创建工人(线程) 例:ForkJoinTask实现归并排序 ForkJoin计算流程 前言: ForkJoin是在Java7中新加入的特性,大家可能对其比较陌生,但是Java8中Stream的并行流parallelStream就是依赖于ForkJoin.在ForkJoin体系中最为关键的就是ForkJoinTask和ForkJoinPool,ForkJoin就是利用

  • 一文带你了解Java中的Object类及类中方法

    目录 1. Object类介绍 2. 重写toString方法打印对象 3. 对象比较equals方法 4. hashCode方法 1. Object类介绍 Object是Java默认提供的一个类.Java里面除了Object类,所有的类都是存在继承关系的.默认会继承Object父 类.即所有类的对象都可以使用Object的引用进行接收. 范例:使用Object接收所有类的对象 class Person{} class Student{} public class Test { public s

  • 一文带你了解Qt中槽的使用

    目录 一.建立槽和按钮之间的连接 二.槽函数的定义 一.建立槽和按钮之间的连接 connect(信号发送者,发送的信号,信号接收者,信号接收者的槽函数) 1.例子 connect(ui->pushButton,SIGNAL(clicked(bool)),this,SLOT(showinfo())); 解释: 信号反发送者:pushButton(这是一个按钮),发送信号:clicked(点击按钮),信号接收者:this(本类),信号接收者的槽函数:showinfo(点击按钮后响应的函数) 二.槽函

  • 一文带你了解Vue3中toRef和toRefs的用法

    toRef 顾名思义,不是ref 响应式数据,给它转成ref 响应式数据 通俗易懂的理解: <template> <h3>姓名:{{ person.name }}</h3> <h3>年龄:{{ person.age }}</h3> <h3>薪资:{{ person.job.j1.salary }}</h3> <button @click="person.name += '!'">修改姓名&l

随机推荐