首页 > 编程语言 >C++ 虚继承,虚函数与纯虚函数整理

C++ 虚继承,虚函数与纯虚函数整理

时间:2023-08-20 16:58:34浏览次数:31  
标签:函数 继承 C++ class 纯虚 派生类 public

1. 虚继承

虚继承是用于解决多继承中“菱形继承”问题的一种技术。在多继承中,如果两个基类都继承了同一个基类,派生类会包含两份该基类的数据成员和函数成员,从而产生冗余和二义性。虚继承的作用就是消除这种冗余。

虚继承的定义方式是在继承关系中添加关键字“virtual”,如下所示:

class A {
public:
    int a;
};

class B : virtual public A {
public:
    int b;
};

class C : virtual public A {
public:
    int c;
};

class D : public B, public C {
public:
    int d;
};

在上面的代码中,B 和 C 都使用了虚继承来继承 A。这样在 D 中,只有一份 A 的数据成员和函数成员,避免了冗余和二义性的问题。

需要注意的是,虚继承会导致派生类的内存布局发生变化,从而影响程序的性能和空间占用。因此,在使用虚继承时需要仔细考虑继承关系和设计。

2. 虚函数

虚函数是指在基类中声明的函数,在派生类中可以重新定义并赋予新的功能,使得派生类的对象调用该函数时能够根据对象的实际类型动态地绑定到相应的函数实现上。该特性被称为多态,是面向对象编程的重要特点之一。

虚函数的定义方式是在函数声明前添加关键字“virtual”,如下所示:

class A {
public:
    virtual void func() {}
};

派生类可以覆盖基类的虚函数,方法是在函数定义前使用相同的函数签名定义一个函数,如下所示:

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

当调用一个虚函数时,编译器会根据对象的实际类型确定要调用的函数版本。例如:

A* ptr = new B;
ptr->func(); // 调用 B::func,而不是 A::func

3. 纯虚函数

纯虚函数是一个在基类中声明的没有实现的虚函数,通常用于定义抽象接口或者抽象类。我们可以通过在函数声明后面加上 "= 0",来将一个普通的虚函数变成一个纯虚函数。如下所示:

class Base {
public:
    virtual void func() = 0; // 纯虚函数声明
};

这个语法告诉编译器 func() 函数是一个纯虚函数,因此它必须在任何派生类中被实现。一个类如果包含纯虚函数,那么它就是一个抽象类,不能被直接实例化。

class Derived : public Base {
public:
    void func() override {} // 派生类必须实现纯虚函数
};

当我们派生一个子类时,必须重写基类的纯虚函数,否则子类也会成为抽象类。下面是一个例子:

class Shape {
public:
    virtual void draw() = 0; // 纯虚函数
};

class Circle : public Shape {
public:
    void draw() override {
        // 实现 draw() 的具体操作
    }
};

class Square : public Shape {
public:
    void draw() override {
        // 实现 draw() 的具体操作
    }
};

在上面的例子中,Shape 类是一个抽象类,它只声明了纯虚函数 draw(),子类 Circle 和 Square 继承了 Shape,必须实现 draw() 函数。这种方式可以实现多态性,通过 Shape 的指针或者引用调用派生类重写的函数。

标签:函数,继承,C++,class,纯虚,派生类,public
From: https://www.cnblogs.com/orzmiku/p/17644236.html

相关文章

  • C++ 函数指针与Lambda匿名函数
    函数指针c语言学过了,这里简单记一下,下面举例一个用法就行:#include<iostream>#include<vector>template<classT>voidprint(Tv){ std::cout<<v<<std::endl;}template<classT1,classFunc>voidForEach(std::vector<T1>&v,Func......
  • C++ Template
    Template模板,其他语言叫泛型,或者说是泛型的爷爷的爷爷(模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。模板是创建泛型类或函数的蓝图或公式。库容器,比如迭代器和算法,都是泛型编程的例子,它们都使用了模板的概念。直接上例子例一先看这段代码:#inc......
  • shell脚本中的函数与数组
    一.函数编写脚本时,有些脚本可以反复使用,可以调用函数来解决语句块定义成函数约等于别名函数使用方法:定义函数再引用函数建立函数,基本格式1.function函数名{ 命令序列}2.函数名(){命令序列}3.functionfunc_name(){...函数体...}1.注意事项直接写......
  • C++ 可见性
    可见性比较简单,很好理解,长话短说=v=外部的类派生类同一个类private不可访问不可访问可以访问protected不可访问可以访问可以访问public可以访问可以访问可以访问#include<iostream>usingnamespacestd;classA{private: intx;protected......
  • C++ 成员初始化列表
    成员初始化列表成员初始化列表时对象初始化成员变量的一种方法。使用方式如下(两种书写习惯)ClassName(args):varName1(value),...,varNameN(value){//这是一个构造函数//...CODE...}ClassName(args):varName1(value),...,varNameN(value){//这......
  • C++ const和mutable
    const和mutable这里只说const在c++中的特殊用法。用const修饰函数的成员函数。被const修饰的成员函数无法修改函数内的其他成员。可以认为这个函数变成了一个“只读”的状态。Likethis://注意const在括号后面,不要写成constxxxxx(){...}了intgetStatus()const{ returnm......
  • C++ new和delete
    new关键字在C++中,当我们在函数内声明一个变量时,变量会被放在栈(stack)中。栈中的内存离开代码块就被释放了。而且栈的内存很小,当我们声明了大量变量可能会导致内存不足。内存除了栈以外,还有堆(heap),当我们在函数外声明一个全局变量时,这个变量就放在堆上。堆是程序未使用的内存,可以被......
  • c++ 丢失笔记 [运算符重载、this指针、复制与拷贝构造、生存周期、箭头操作符]
    运算符重载、this指针、复制与拷贝构造、生存周期、箭头操作符有一部分是学校的OJ里做题需要就提前学了,然后没记笔记,有一部分是笔记丢了。不打算补这些笔记。不过还是在这里mark一下++运算符的重载。因为++运算符可以前置也可以后置,所以这里需要注意一下,如果是后置++,需要一个in......
  • C++ 隐式转换与explicit关键字
    隐式转换与explicit关键字隐式转换函数构造的隐式转换,直接上代码:#include<bits/stdc++.h>classEntity{private: std::stringm_Name; intm_Age;public: Entity(conststd::string&name) :m_Name(name),m_Age(-1){} Entity(intage) :m_Name("Unknown"),m_A......
  • C++ Vector数组优化
    Vector数组优化问题这是一段没有优化的代码:#include<iostream>#include<vector>classEntity{public: intx,y;public: Entity(intx,inty) :x(x),y(y){} Entity(constEntity&e) :x(e.x),y(e.y){ std::cout<<"Copied!"<<st......