c++中虚函数的实现详解

现在我来详细讲解一下 "C++中虚函数的实现详解" 的完整攻略,包含以下内容:

1. 什么是虚函数

虚函数是C++中的一种特殊函数,可以让我们在基类中声明一个方法,在子类中对其进行重新定义,从而实现多态的特性。在实际应用中,我们通常通过将基类指针指向子类对象的方式来调用虚函数。

2. 虚函数的实现

2.1 虚函数表

C++中通过虚函数表(vtable)来实现虚函数的机制,虚函数表是一个存储虚函数指针的数组,存储在类的对象中,每一个类都分配有一个虚函数表,在其中存储了该类中的所有虚函数。

在使用虚函数时,C++使用对象的指针或引用来调用虚函数,首先会根据指针或引用中所存储的虚函数表指针来找到虚函数表,然后再根据函数在虚函数表中的位置来调用对应的虚函数。

2.2 虚函数表指针

对于每一个基类对象,在它的内存布局中都会包含一个虚函数表指针,指向基类所对应的虚函数表,在多继承的情况下,每一个包含虚函数的基类都有一个虚函数指针。在基类中,如果定义了虚函数,那么在调用虚函数时,会从基类的虚函数表中找到对应的函数,再进行调用。如果子类对虚函数进行了重写,那么会在子类的虚函数表中替换对应的虚函数指针。

3. 示例说明

示例1:调用基类和派生类中的虚函数

#include<iostream>

using namespace std;

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

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

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

int main()
{
    Base *ptr;
    Derived1 d1;
    Derived2 d2;
    ptr = &d1;//ptr指向Derived1对象
    ptr -> print();//调用派生类Derived1的虚函数print()
    ptr = &d2;//ptr指向Derived2对象
    ptr -> print();//调用派生类Derived2的虚函数print()
    Base b;
    ptr = &b;//ptr指向父类对象
    ptr -> print();//调用父类中的虚函数print()
    return 0;
}

输出结果为:

derived class 1
derived class 2
base class

该示例中,我们定义了一个基类 Base,它有一个虚函数 print,并且我们从它派生出了两个子类 Derived1Derived2,它们重写了基类的虚函数 print。在主函数中,我们定义了一个基类指针 ptr,并且先让它指向派生类 Derived1 的对象,再调用 ptrprint 函数。此时会调用派生类 Derived1print 函数,输出 "derived class 1"。然后我们让 ptr 指向另一个派生类 Derived2 的对象,再次调用 ptrprint 函数,此时会调用派生类 Derived2print 函数,输出 "derived class 2"。最后我们定义一个基类对象 b,让 ptr 指向它,并调用 ptr 的虚函数 print,此时会调用基类 Base 的虚函数 print,输出 "base class"。

示例2:含有虚函数的多态类的对象布局

#include<iostream> 

using namespace std; 

class Point { 
public: 
    virtual void show() 
    { 
        cout << "Point "; 
    } 
}; 

class Point2D : public Point { 
public: 
    void show() 
    { 
        cout << "Point2D "; 
    } 
private: 
    int z = 0; 
}; 


int main() 
{ 
    Point p; 
    Point2D p2d; 

    Point *ptr = &p2d; 
    cout << "size of Point: " << sizeof(p) << endl; 
    cout << "size of Point2D: " << sizeof(p2d) << endl; 
    cout << "size of ptr: " << sizeof(ptr) << endl; 

    return 0; 
} 

输出结果为:

size of Point: 8
size of Point2D: 16
size of ptr: 8

在该示例中,我们定义了一个虚函数 show,它被声明为虚函数,同时从该类派生出了一个子类 Point2D,并且重写了 show 函数。在主函数中,我们定义了一个基类对象 p 和一个派生类对象 p2d,然后再定义一个基类指针 ptr,并将其指向派生类对象。最后我们分别输出 pp2dptr 对象的大小。需要注意的是,由于各个编译器编译出来的结果可能不同,因此在具体的编译器中可能会得到不同的输出结果。在该示例中,由于 Point2D 类中新增了一个成员变量 z,因此其大小为16字节,而 Point 类中没有新增任何成员变量,因此其大小为8字节。指向 PointPoint2D 类的指针都是8字节的大小,无论该指针所指向的对象是哪一个类。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:c++中虚函数的实现详解 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • C语言实现线性动态(单向)链表的示例代码

    下面是详细讲解“C语言实现线性动态(单向)链表的示例代码”的完整攻略: 线性动态(单向)链表是什么? 线性动态(单向)链表是一种动态数据结构,由若干个节点组成。每个节点包含两个部分:数据部分和一个称为指针的部分。指针指向下一个节点,最后一个节点指向空地址(NULL)。链表起始点称为头节点,最后一个节点称为尾节点。 实现步骤 1. 定义节点结构体 定义节点结构…

    C 2023年5月23日
    00
  • C语言传递简单字符串

    C语言传递简单字符串 在C语言中,传递简单字符串有两种方式:指针和字符数组。以下分别介绍这两种方式的使用方法。 使用指针传递简单字符串 在C语言中,传递字符串的方式通常是通过使用指针。 指针是一种引用类型,它存储了内存地址的值。C语言中字符串实际上是由一系列字符组成的字符数组,它们在内存中是连续存储的。一个指针可以指向字符数组的第一个元素,也就是字符串的首地…

    C 2023年5月9日
    00
  • 详解_beginthreadex()创建线程

    当我们需要在程序中实现多线程并行操作时,可以使用C或C++中的beginthreadex函数来创建线程。该函数用于创建一个新线程并在其中运行指定的函数。下面是完整的攻略,包括使用示例。 一、语法 uintptr_t _beginthreadex( void* security, unsigned stack_size, unsigned(__stdcall*…

    C 2023年5月22日
    00
  • C语言贪吃蛇经典小游戏

    下面是关于C语言贪吃蛇经典小游戏的完整攻略: 1.主要规则 在贪吃蛇游戏中,玩家需要通过操纵蛇将食物吃掉来增加自身得分,同时要避免蛇头碰到墙壁或者自己的身体,否则游戏失败。在游戏过程中,蛇头碰到界面的边缘将会被传送至对面的边缘。游戏结束后会显示玩家得分及重新开始游戏选项。 2.游戏操作 通过键盘的方向键控制蛇的移动,W键向上,A键向左,S键向下,D键向右; …

    C 2023年5月30日
    00
  • 详解C++编程中的vector类容器用法

    详解C++编程中的vector类容器用法 简介 在 C++ 中,vector 是一个非常实用的容器类,它可以动态调整大小并提供了一系列方便的操作函数。在本文中,我们将详细介绍 vector 类的使用方法,以便能够更好地应用 vector 容器类进行 C++ 编程。 如何使用 vector 首先需要在头文件中包含 vector: #include<vec…

    C 2023年5月22日
    00
  • C语言实现火车订票系统

    实现火车订票系统的完整攻略分为以下几个步骤: 1. 设计数据库 火车订票系统需要一个数据库来存储车次信息、座位信息、乘客信息等。可以使用MySQL或者SQLite等关系型数据库。设计数据库时需要考虑信息的表结构、字段类型、约束条件等。以下是一个汽车票订购系统的数据库设计: 车次信息表:train_info 字段:train_id, start_station…

    C 2023年5月22日
    00
  • C++之CWnd窗口框架实例

    下面详细讲解一下“C++之CWnd窗口框架实例”的完整攻略。 C++之CWnd窗口框架实例 简介 CWnd是MFC框架中的一个基类,用于创建窗口。它具有以下特点: 可以接收和处理系统消息,如鼠标消息、键盘消息等; 可以在上面绘制图形; 可以在其上创建子控件等; 创建窗口 创建CWnd窗口的方法如下: BOOL CWnd::Create( LPCTSTR lp…

    C 2023年5月24日
    00
  • C语言MultiByteToWideChar和WideCharToMultiByte案例详解

    C语言MultiByteToWideChar和WideCharToMultiByte案例详解 简介 在C语言中,字符编码的转换是一个基本操作,这通常需要用到 MultiByteToWideChar 和 WideCharToMultiByte 这两个Windows API函数。 MultiByteToWideChar 将ANSI格式的字符串(即单字节字符串)转…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部