c++对象和内存 对虚继承的讨论

C++ 虚函数/虚继承内存布局 1 前言 1.1 多态 C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。 多态分为静态多态和动态多态。 (1)静态多态:是发生在编译期,是一种早绑定。通过函数重载和泛型编程实现。 (2)动态多态:是发生在运行期,是一种晚绑定。通过虚函数实现。 注意以下函数不能是虚函数: (1)普通函数(非类成员函数) (2)静态函数 ... 阅读详情

1          类、对象和内存

1.1        通过内存看对象

我们先回顾一下类和对象的定义,类是定义同一类所有实例变量和方法的蓝图或原型;对象是类的实例化。从内存的角度可以对这两个定义这样理解,类刻画了实例的内存布局,确定实例中每个数据成员在一块连续内存中的位置、大小以及对内存的解读方式;对象就是系统根据类刻画的内存布局去分配的内存。除了实例变量和方法,类也可以定义类变量和类方法,这是我们通常所说的静态变量和静态函数,它们不属于某个具体的对象,而是属于整个类,所以不会影响对象的内存布局和内存大小。通过以上的讨论我们可以知道:对象本质上就是一块连续的内存,对象的类型(类)就是对这块内存的解读方式。在c++中我们可以通过四个类型转换运算符改变对象的类型,这种转换改变的是内存的解读方式,不会修改内存中的值。修改对象内存值的合法途径是通过成员函数/友元函数修改对象的数据成员。通过成员函数修改对象的值是c++语言保证对象安全的一种机制,但这种机制不是强制的,你可以通过暴力的非法手段避开这个机制(比如你可以取得对象的起始地址,然后根据对象的内存布局任意修改内存的值),除了极其特殊情况,这种人为非法手段都应当被禁止,因为这种暴力代码难于理解、不便移植、极易出错;另外程序在运行过程中由于代码中的某些缺陷也会非法修改对象内存的值,这是我们程序中许多疑难bug的根源。所以正确的编写类,理解对象在内存的运行特点,合理的控制对象的创建和销毁是一个程序稳定运行的基本保证。

1.2        不同内存区域的对象

在C++中,对象通常存放在三个内存区域:栈、堆、全局/静态数据区;相对应的,在这三个区域中的对象就被称为栈对象、堆对象、全局/静态对象。

全局/静态数据区:全局对象和静态对象存放在该区,在该内存区的对象一旦创建后直到进程结束才会释放。在其生存期内可以被多个线程访问,它可以做为多线程通信的一种方式,所以对于全局对象和静态对象要考虑线程安全,特别是对于函数中的局部静态变量,容易忘记它的线程安全性。全局对象和一些静态对象有一个特点:这些对象的初始化操作先于main函数的执行,而且这些对象(可能分布在不同的源文件中)初始化顺序没有规定,所以在它们的初始化中不要启动线程,同时它们的初始化操作也不应有依赖关系。

堆:堆对象是通过new/malloc在堆中动态分配内存,通过delete/free释放内存的对象。我们可对这种对象的创建和销毁进行精确控制。堆对象在c++中的使用非常广泛,不同线程间、函数间的对象共享可以使用堆对象,大型对象一般也使用堆对象(栈空间是有限的),特别是虚函数多态性一般是由堆对象实现的。使用堆对象也有一些缺点:1.需要程序员管理生存周期,忘记释放会有内存泄露,多次释放可能造成程序崩溃,通过智能指针可以避免这个问题;2.堆对象的时间效率和空间效率没有栈对象高,堆对象一般通过某种搜索算法在堆中找到合适大小的内存,比较耗时间,另外从堆中分配的内存大小会比实际申请的内存大几个字节,比较耗空间,尤其是对于小型对象这种损耗是非常大的;3.频繁使用new/delete 堆对象会造成大量的内存碎片,内存得不到充分的使用。对于2,3两个问题可以通过内存一次分配,多次使用的方法解决,更好的方法是根据业务特点实现特定的内存池。

栈:栈对象是自生自灭型对象,程序员无需对其生存周期进行管理。一般,临时对象、函数内的局部对象都是栈对象。使用栈对象是高效的,因为它不需要进行内存搜索只进行栈顶指针的移动。另外栈对象是线程安全的,因为不同的线程有自己的栈内存。当然,栈的空间是有限的,所以使用中要防止栈溢出的出现,通常大型对象、大型数组、递归函数都要慎用栈对象。

2          C++对象的创建和销毁

C++类有四个基本函数:构造函数、析构函数、拷贝构造函数、赋值运算符重载函数,这四个函数管理着C++对象的创建和销毁,正确而完整地实现这些函数是C++对象安全运行必要保证。

2.1        构造/析构

创建一个对象有两个步骤:1.在内存中分配sizeof(CAnyType) 字节数的内存;2.调用合适构造函数初始化分配的内存。C++对象的大小由三个因素决定:1.各个数据成员的大小;2.由字节对齐产生的填充空间的大小;3.为支持虚机制编译器添加的一个指针,大小是四个字节,虚机制指针有两种:1.支持虚函数的虚表指针,2.支持虚继承的虚基类指针。虚继承时,派生类只保存一份被继承的基类的实体,比如下面例子的菱形继承关系中,类D中只有一份类A的实体。另外,类A是一个空类,但sizeof(A)大小不是0,而是1,这是因为需要用这一个字节来唯一标识类A在内存中的不同对象。

 

Class A{};

Class B : virtual public A {};

Class C : virtual public A {};

Class D:public B, public C {}

 

 

 

由上面讨论知道,类中除了有编程人员写的数据成员,有时还有一些由编译器为支持虚机制而偷偷给你添加的成员,这些成员我们在代码中不会直接用到,但有可能被我们的代码非法修改。比如不恰当的构造函数会修改虚机制指针的值,在写构造函数时我们经常使用如下的代码对整个对象进行初始化:

                      memset(this, 0, sizeof(*this));

这种初始化方式只能在类不涉及虚机制的情况下使用,否则它会修改虚机制指针,使类对象的行为无定义。

销毁一个对象也有两个步骤:1.调用析构函数;2.向系统归还内存。析构函数的作用是释放对象申请的资源。析构函数通常是由系统自动调用的,在以下几种情况下系统会调用析构函数:1.栈对象生命周期结束时:包括离开作用域、函数正常return(不考虑NRV优化)、函数异常throw;2.堆对象进行delete操作时;3.全局对象在进程结束时。析构函数只在一种情况下需要被显式的调用,那就是用placement new构建的对象。当类里包含虚函数的时候我们应该声明虚析构函数,虚析构函数的作用是:当你delete一个指向派生类对象的基类指针时保证派生类的析构函数被正确调用。有许多资源泄露的问题就是因为没有正确使用虚析构函数造成的,这种资源泄露有两种:1.派生类里直接分配的资源;2.派生类里的成员对象分配的资源。尤其是第二类,隐蔽性非常高。

构造和析构是一组被成对调用的函数,特别是对于栈对象,调用是由系统自动完成的,所以我们可以利用这一特性将一些需要成对出现的操作分别封装在构造和析构函数里由系统自动完成,这样可以避免由于编程时的遗漏而忘记进行某种操作。比如资源的申请和释放,多线程中的加锁和解锁都可以利用栈对象的这一特性进行自动管理。

 

 

2.2        拷贝/赋值

拷贝构造函数、赋值运算符重载函数是一对孪生兄弟,通常一个类如果需要显式写拷贝构造函数,那么它也需要显式写赋值运算符重载函数。拷贝构造函数的功能是用已存在的对象构造一个新的对象,赋值运算符重载函数的功能是用已存在的对象替换一个已存在的对象。看下面几条语句:

string str1 = “string test”;  //调用带参数的构造函数

string str2(str1);         //调用拷贝构造函数

string str3 = str1;        //调用拷贝构造函数

string str4;             //调用默认构造函数

str4 = str3;             //调用赋值运算符重载函数

拷贝构造函数、赋值运算符重载函数原型如下:

class string

{

private:

    char* m_pStr;

    int   m_nSize;           

public:           

       string ();                             //默认构造函数

string (const char* pStr);                //带参数的构造函数

       ~ string ();

    string (const string & cOther);            //拷贝构造函数

    string & operator=(const string & cOther);  //赋值运算符重载函数

}

 

这两个函数的参数类型都是const string &,我们知道对于c++对象通常以常引用作函数的参数,这样可以提高参数的传递效率,以对象作为函数参数时会调用拷贝构造函数生成一个临时对象供函数使用,效率较低。拷贝构造函数是一个很特殊的函数,对于其他函数用对象作为函数参数顶多是效率的损失,但对拷贝构造函数用对象作为函数参数就会形成无限递归调用,所以拷贝构造必须以常引用作为参数。

拷贝构造函数在c++编译器中有缺省的实现,实现的方式是按位对内存进行拷贝(memcpy(this, & cOther, sizeof(string)),如果缺省的实现满足我们的要求那就不需要显式的去实现这个函数,否则就必须实现,判断是否满足位拷贝语义的依据是类的成员数据中是否需要动态分配其他资源,比如上面的string类,成员m_pStr需要从堆中分配内存来存放具体的字符串,这块堆内存是位拷贝语义无法正确管理的,所以在string对象进行拷贝/赋值时编程人员需要负责管理这块内存。通常在三种情况下会调用拷贝构造函数,1. 一个对象以值传递的方式传入函数;2. 一个对象以值传递的方式从函数返回;3. 一个对象需要通过另外一个对象进行初始化。如果你确保对类对象的使用不会出现以上三种情况,那就说明你根本不需要拷贝构造函数,直接将拷贝构造函数私有化是最安全的选择。从以上的讨论我们知道,对于拷贝构造函数有三种处理策略(对于赋值运算符重载函数同样适用):1.什么都不写,按缺省的处理;2.显式写拷贝构造;3.将拷贝构造私有化。在写一个类前,我们必须分析类自身的实现方式以及对类对象的使用方式,明确选择一种策略,如果你放弃选择你就为将来可能出现的bug埋下一个伏笔。

上面讨论了拷贝/赋值函数的选择策略,下面看看它们具体的实现方式。拷贝构造函数的功能由一个对象构造一个新的对象,只要一个Copy操作就可以完成。赋值运算符重载函数的功能是由一个对象替换一个已存在的对象,完成这个功能需要三个操作:自赋值检查、Clear原有对象、Copy新对象。如string类的实现:

class string

{

private:

    char* m_pStr;

    int   m_nSize;           

public:           

       string ();            //默认构造

string (const char* pStr);   //带参数的构造函数

       ~ string ();

 

    string (const string & cOther)  //实现拷贝构造函数

    {

       Copy(cOther);

    }

 

    string & operator=(const string & cOther)  //实现赋值运算符重载函数

    {

       if (this != & cOther)

       {

          Clear();

          Copy(cOther);

       }

       return *this;

    }

 

private:

    void Copy(const string & cOther)

    {

        m_pStr = new char [cOthre. m_nSize+1];

        strcpy(m_pStr, cOther. m_pStr);

        m_nSize = cOther.m_nSize;

    }

 

    void Clear()

    {

       if (m_pStr != NULL)

       {

           delete[] m_pStr;

           m_pStr = NULL;

       }

       m_nSize = 0;

      

    }

}

 

string类中这两个函数的实现模式可以在其他类中直接套用,只需要改动Copy和Clear()函数即可。

3          总结

作为c++程序员每天都要和类、对象以及内存打交道,写一个类实现某项功能不难,但要实现一个健壮的、可重用的、易扩展的类就不是很容易了。很多时候我们写一个类时用的还是c的思维,对类的四个基本函数考虑的不够周到仔细,对类对象在不同内存区域运行特点理解不够,容易产生一些低级的bug,而且对后续的代码维护扩展也带来难度。本文中对这些内容做了基本的介绍,希望对大家有些帮助。

C++虚继承对内存空间影响分析 1、  虚继承概念虚继承 (也称为共享继承)是面向对象编程中的一种技术,是指一个指定的基类,在继承体系结构中,将其成员数据实例共享给也从这个基类型直接或间接派生的其它类。虚继承是多重继承中特有的概念。虚基类是为解决多重继承而出现的。2、  虚继承和虚基类虚继承:在继承定义中包含了virtual关键字的继承关系;虚基类:在虚继承体系中的通过virtual继承而来的基类举例说明:class CSubC... 阅读详情

相关推荐

浅谈C++多态实现原理(虚继承的奥秘)

根据我的已有知识,如果要实现C++的多态,那么,基类中相应的函数必须被声明为虚函数(或纯虚函数)。举个例子: class Point { public: Point(float x = 0.0, float y = 0.0) : _x(x), _y(y) { } virtual float z(); //virtual function protected: float _x, _y; }...

机器学习 1336

c++对象和内存

 1          类、对象和内存1.1        通过内存看对象我们先回顾一下类和对象的定义,类是定义同一类所有实例变量和方法的蓝图或原型;对象是类的实例化。从内存的角度可以对这两个定义这样理解,类刻画了实例的内存布局,确定实例中每个数据成员在一块连续内存中的位置、大小以及对内存的解读方式;对象就是系统根据类刻画的内存布局去分配的内存。除了实例变量和方法,类也可以定义类变量和

cad_vc的专栏 898

C++内存分布 虚表 虚指针(非常重要)

C++内存分布 虚表 虚指针: class Base { public: int m_base; }; class DerivedA: public Base { public: int m_derivedA; }; class DerivedB: public Base { public: int m_derivedB; }; class D

hacker00011000的专栏 1万+

<C++ 略识> 之引用类型

引用就是变量的别名,引用符号:&。 1、基本数据类型的引用 int a = 3; int &b = a; //定义了b是a的引用,即b是a的别名 注意:引用必须初始化,即:在起别名时,一定要指明给哪个变量起的别名;其次,对别名的修改,就是对实际变量的修改。 2、结构体类型的引用 typedef struct {        int x;        int y; }Coor

浅语 830

c++中超级详细的一些知识,新手快来

这篇文章主要来讨论C++对象在内存中的布局,属于第二个概念的研究范畴。而C++直接支持面向对象程序设计部分则不多讲。虚函数表解析。含有虚函数或其父类含有虚函数的类,编译器都会为其添加一个虚函数表,vptr,先了解虚函数表的构成,有助对C++对象模型的理解。虚基类表解析。虚继承产生虚基类表(vbptr),虚基类表的内容与虚函数表完全不同,我们将在讲解虚继承时介绍虚函数表。对象模型概述:介绍简单对象模型、表格驱动对象模型,以及非继承情况下的C++对象模型。继承下的C++对象模型。

阿玥的小博客 6587

mysql数据目录迁移后表不存在_mysql 直接从date 文件夹备份表,还原数据库之后提示 table doesn`t exist的原因和解决方法...

补充:正常情况下,建议数据库备份最好用工具进行备份,通过拷贝数据库表进行数据迁移,不同的环境会出现各种不同的意外问题。背景:今天在整理一个网站的时候,操作系统由于系统自动更新导致一直出现系统蓝屏死机,唉,悲剧了,于是重新安装了系统 windows server 2008 enterprise 32bit。详情:系统安装完成后,重新配置之前那个网站,appache服务配好之后,再配置数据的时候是这样...

weixin_39628271的博客 2674

C++菱形继承对象内存布局实战讲解和分析

本文主要讲解C++对象模型中的菱形继承的对象模型,分别讨论基类对象变量和函数的继承问题。 何为菱形继承: 菱形继承是指一个基类(Base)派生出两个派生类(Derived1,Derived2),然后这两个派生类(Derived1,Derived2)派生出一个最终的派生类,如1.1的下图所示。 一、菱形继承之非虚继承 1.1类Base、派生类Derived1、派生类Derived2、最终派生类DDerived的UML结构图 1.2类Base、派生类Derived1、派生类Derived2、最终派生类DDer

净无邪博客 3100

深入了解神经网络:构建人工智能的基石

这篇博客将为您解释神经网络的构造,让您能够理解这个令人着迷的领域的基本工作原理。神经网络是人工智能领域的关键技术,它们的构造基于神经元的灵感,并结合了数学、统计和机器学习的原理。输入可以类比为神经元的树突,而输出可以类比为神经元的轴突,计算则可以类比为细胞核。较好的方法就是预先设定几个可选值,通过切换这几个值来看整个模型的预测效果,选择效果最好的值作为最终选择。:这是神经网络的核心部分,包含多个层次的神经元。、神经网络结构图中的拓扑与箭头代表着预测过程时数据的流向,跟训练时的数据流有一定的区别;

AI_dataloads的博客 2万+

C++虚继承的一些细节

C++虚继承的一些细节

doubleintfloat的博客 353

自动配胶机的PLC控制系统设计

我们根据自动配胶机的控制需求,编写了相应的PLC程序。PID温度控制算法的实现方面,我们采用了经典的PID控制算法,通过不断调整加热器的功率,实现对胶水混合温度的精确控制。在PLC程序中,我们编写了PID控制算法的程序模块,通过实时采集温度传感器的数据,计算温度偏差和偏差变化率,并根据PID控制算法计算出加热器的功率输出值,实现对温度的精确控制。在系统调试阶段,我们对自动配胶机的各个部分进行了详细的测试和调试,包括气路和液路的开关测试、传感器的精度测试、步进电机的位置和速度测试以及PLC程序的逻辑测试等。

lagougongzuoshi的博客 1228

昇腾NPU实战:PaddleSpeech语音模型高效部署与性能优化指南

本文详细介绍了如何在华为昇腾NPU上高效部署PaddleSpeech语音识别模型。通过使用官方Docker镜像、解决依赖冲突、修改源码适配NPU算子,并应用混合精度与批处理等优化技巧,实现模型在昇腾平台上的稳定运行与性能提升,为AI语音应用提供高性价比的国产硬件部署方案。

weixin_29214691的博客 181

[阅读型]深入理解C++多继承(multiple inheritance)与虚继承(virtual inheritance)的底层原理与实现-以g++为例

目录前言1. virtual 函数需要解决的问题2. 单继承3. 多继承4. 虚继承 前言 做安全的肯定是要深究一下,特别是了解其c++对象的memory layout和一些编译器生成的固定代码。另一方面c++开发者,既然是选择折腾c++,实际上也有了解的必要。本文不是讨论怎么用继承去实现一个良好的设计,而是讨论c++编译器是怎么支持这个特性的。这里不要把编译器想象的多么神通广大,实际上它是通过生成一些固定的代码与数据来实现的。主要参考文献c++的abi1。 极具争议的多继承与虚继承为啥这么恶心? 因能力有

easy_level1的博客 2207

ENVI入门系列教程---一、数据预处理---1.1基本操作--5.x以后的界面(新界面)

every blog every motto: You never know how strong you really are until being strong is the only choice you have。 0. 前言 本系列教程旨在系统学习并梳理ENVI。说来惭愧,作为一名GISer,对ENVI这类软件还不能熟练掌握,这也是本系列教程的初衷。种一棵树最好的时间是十年以前,其次是...

胡侃有料的博客 1万+

图说C++对象模型:对象内存布局详解

0.前言 文章较长,而且内容相对来说比较枯燥,希望对C++对象的内存布局、虚表指针、虚基类指针等有深入了解的朋友可以慢慢看。 本文的结论都在VS2013上得到验证。不同的编译器在内存布局的细节上可能有所不同。 文章如果有解释不清、解释不通或疏漏的地方,恳请指出。 1.何为C++对象模型? 引用《深度探索C++对象模型》这本书中的话: 有两个概念可以解释C++对象模型: 语言中直接支持面向对象程序设计的部分。 对于各种支持的底层实现机制。 直接支持面向对象程序设计,包括了构造函数、析构函数、

肖邦的夜曲的专栏 808

硬件工程师的破局之路:为何你才是考取软考高级架构师的“天选之子”?

硬件工程师如何转型系统架构师:独特优势与实战路径 文章揭示了硬件工程师在考取系统架构设计师证书时的独特优势。作者指出,硬件工程师的全局思维、接口设计能力和可靠性经验正是系统架构的核心要素。通过将硬件经验升维为架构思维(从引脚到接口、从单板到系统、从实现到权衡),硬件背景反而成为竞争优势。文章建议通过知识补全、建立架构决策日志和术语转换练习来备考,并强调硬件工程师在软硬协同时代的独特价值——既能统领硬件设计,又能为软件搭建最佳舞台。文末鼓励硬件工程师以更高视野看待职业发展,将系统架构师认证视为水到渠成的职业升

云轩阁 534

AEJoy —— 最受欢迎的 5 个 Ae 表达方式

NOTE] 原文作者我意识到表达式可能令人生畏,有些人宁愿复制粘贴有用的代码,而不愿学习这门语言。对此我完全理解。因此,我想与您分享我的。这些是我几乎在每个项目中都会使用的表达式,我认为它们极大地提升了工作流程。

ShaderJoy 的兴趣技术杂货铺 364

gcc下c++对象模型,对象内存分布

GCC对象内存布局(win10) gdb调试的一些用法: C:\Users\huangx\Desktop\Test> g++ -std=c++11 -g -o test test.cpp //-g 加入调试信息 C:\Users\huangx\Desktop\Test> gdb test //进入调试 (gdb) set p pretty on //美化print的输出 (gdb) b 47 //break line设置断点 (gdb) r //run 运行程序 (gdb) p d //打印对象

zxc151643的博客 1429

CKA-CN考试之路----2

部分知道就可以了,考试不用输入,后面不再复述.这里我们需要将两端内容凭借成1个yaml。执行题目中给的的命令进行测试。

Q先生 242

C++学习之多重继承,钻石继承,虚继承(二)

多重继承:一个子类可以同时继承多个基类,这样继承方式称为多重继承   向上造型时,编译器会根据各个基类子对象的内存布局,自动进行偏移计算(如,第一个基类子对象的起始地址和整个对象的起始地址一样),以保证指针的类型和所指向的目标基类子对象类型一致。 #include <iostream> using namespace std; class Phone{//电话 publi...

u013511885的博客 304

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C++对象的内存模型

看了C++ under the hood之后,C++对象的内存模型是这样的:涉及到虚的,就需要额外的存储空间。虚这里指的是虚函数和虚继承,额外的存储是对象内部需要存储虚函数表指针和虚基类表指针。 一个类的内存的分布在VC下是这样的:先是非虚基类子对象(包括非虚基类的虚函数表指针和成员),接着是虚基类表指针,接着才是该类本身扩展的成员,然后是虚基类子对象。该类的虚函数如果在基类中虚线,会在对应的虚

zhouguoqionghai的博客 3216

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

C++对象模型:g++实现(二)

至此,我们可以总结在基类有虚函数的时候C++的内存布局了:派生类新增的虚函数并不会导致新的虚表指针的诞生,而是会复用第一个虚表指针,使其指向一个新的虚表,这个虚表前几项都是基类的虚函数地址(当然,如果派生类覆写[在这种情况下,派生类会继承基类的虚函数,也会复用基类放置虚表指针的内存位置,无论基类有没有定义虚函数,有没有新增虚函数,都不会增加新的虚表指针,而是复用基类的虚表指针的内存位置。]了该虚函数,新的虚函数地址会在该位置覆盖基类的虚函数地址),后面则是派生类的虚函数地址。这个虚函数,是它的地址吗?

Gefangenes的博客 169

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

《深度探索C++对象模型》读书笔记-第三章

这一章主要进一步讨论C++对象的内存布局, 特别是在引入继承, 虚函数, 多继承, 虚继承后对内存布局的影响, 还包含编译器对相关特性的实现方式和优化. 下面的代码运行于 Archlinux 4.18 x86_64, 编译器是gcc 8, 使用gdb 8调试. 不含数据成员的类对象 对于不存在继承和虚函数的类, 没有数据成员时, 其大小至少是1 byte, 以保证变量有唯一的地址. 当加上虚函数后, 由于有虚函数指针, 对象大小等于一个指针的大小, 32位系统中是4 bytes, 64位系统中是8 b

Estelle 352

C++中虚函数工作原理和(虚)继承类的内存占用大小计算

一、虚函数的工作原理       虚函数的实现要求对象携带额外的信息,这些信息用于在运行时确定该对象应该调用哪一个虚函数。典型情况下,这一信息具有一种被称为 vptr(virtual table pointer,虚函数表指针)的指针的形式。vptr 指向一个被称为 vtbl(virtual table,虚函数表)的函数指针数组,每一个包含虚函数的类都关联到 vtbl。当一个对象调用了虚函数,实际

Hackbuteer1的专栏 6万+

C++类对象内存模型与成员函数调用分析(下)

<br />2.4.2 多重继承下的虚拟函数<br /><br />多重继承下的虚拟函数主要有一下几个麻烦:<br />1.         几个父类都声明了相同原型的virtual函数;<br />2.         有不止一个父类将其析构函数声明为虚拟;<br />3.

左手为你画情 4461
上一篇: otool 与dylib
下一篇: Unix常用命令
dadalan
博客等级 码龄20年 428粉丝 770原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值