仪器网(yiqi.com)欢迎您!

| 注册 登录
网站首页-资讯-专题- 微头条-话题-产品- 品牌库-搜索-供应商- 展会-招标-采购- 社区-知识-技术-资料库-方案-直播- 视频

问答社区

C++虚表问题

7856xjgh 2017-10-02 03:59:31 369  浏览
  • 请教一个问题,C++中从虚基类派生出来的类,如果原虚基类中的虚函数在该类中还是虚函数,那么系统会不会给这个派生类创建虚表?或者是只分配一个指针指向diyi次出现这些虚函数的基类的... 请教一个问题,C++中从虚基类派生出来的类,如果原虚基类中的虚函数在该类中还是虚函数,那么系统会不会给这个派生类创建虚表?或者是只分配一个指针指向diyi次出现这些虚函数的基类的虚表? 1楼的朋友谢谢你的回答 我喜欢结交你这样的有研究精神的朋友,你的分析很有研究价值,暂且先不讨论编译器的问题。 我从深入浅出MFC中找到虚表的相关知识,这个肯定不会有错,期待问题能够尽早彻底解决 深入浅出MFC: 1.每一个内涵虚函数的类,编译器都为它做出一个虚拟函数表,表中的每一个元素都指向一个虚函数的地址。 此外,编译器当然也会为类表加上一项成员函数,是一个指向该虚拟函数表的指针(常被称为vptr),每一个由此类别派生出来的类,都有这么一个vptr。 2.虚表以及这种间接呼叫方式。虚表的内容是依据类别中的虚函数声明次序--填入函数指针。派生类别会继承基础类别的虚表(以及所有其他可以继承的成员),当我们在派生类中改写虚函数时,虚表就受了影响;表中的元素所指的函数地址将不再是基类的函数地址,而是派生类的函数地址。 总结:通过深入浅出MFC的内容可以得知: 1,派生类要继承基类的虚表,而不只是说继承基类的虚表指针,所以可以判定,至少从理论上可以判定虚表是要拷贝的,而不是继续用父类虚表,而且多想想也应该可以理解,父类对象指针所指的虚表内容应该和子类不同,因为刚才有提到虚表函数的重定向。可能编译器做了某种优化,再研究 展开

参与评论

全部评论(2条)

  • 隋丶建坤 2017-10-03 00:00:00
    对于一个类如果有虚函数,就会在这个类中创建一个虚表,也就会产生一个虚指针指向这个虚表。 既然有一个指针指向了虚表,这个类派生后,在派生类中就不必再创建虚表,如果派生类还有自己的虚函数,那么只在派生类中创建该虚函数的一个虚表,产生一个指向该虚表的指针。 为每个类设置虚表,初始化虚指针,为虚函数调用插入代码都是自动发生的,不必担心这些。 (我看到过虚继承下虚表问题的分析,直接继承下没看过,特此又分析了一下,修改) #include<iostream> using namespace std; class A { public: virtual void a(){}; }; class B:public virtual A { public: virtual void b(){}; }; int main() { cout<<sizeof(A)<<endl; cout<<sizeof(B)<<endl; } 对于这个程序,你大概是在vc6.0下运行的吧,在vc下结果是4和12。我用的编译器是g++,对于这段程序的结果确实都为4. 因编译器不同导致结果不同这个我倒是没注意,这样可以得出,对虚函数这里的处理机制和编译器也是有关的,g++编译器还是更符合新的标准。 把虚继承virtual去掉再运行,在codeblocks下,g++编译运行结果都为4. vc下编译运行结果也都为4. 在分析一个例子: #include<iostream> using namespace std; class A { char j[3]; public: virtual void a(){}; }; class B:public A { char k[3]; public: virtual void b(){}; }; class C:public B { char m[3]; public: virtual void c(){}; }; int main() { cout<<sizeof(A)<<endl; cout<<sizeof(B)<<endl; cout<<sizeof(C)<<endl; } 这个直接继承的例子,在vc下,codeblocks下结果都为 8 12 16. 再看这个直接继承的例子: #include<iostream> using namespace std; class A { public: virtual void a(){}; }; class B:public A { public: virtual void b(){}; }; class C:public B { public: virtual void c(){}; }; int main() { cout<<sizeof(A)<<endl; cout<<sizeof(B)<<endl; cout<<sizeof(C)<<endl; } vc下河codeblocks下结果都为 4. 这两个程序说明,直接继承下,输出结果应当是本类所占的字节加父类数据成员所占字节,父类的虚指针所占字节没有加上。 加入虚继承后: #include<iostream> using namespace std; class A { char j[3]; public: virtual void a(){}; }; class B:public virtual A { char k[3]; public: virtual void b(){}; }; class C:public virtual B { char m[3]; public: virtual void c(){}; }; int main() { cout<<sizeof(A)<<endl; cout<<sizeof(B)<<endl; cout<<sizeof(C)<<endl; } 这段代码,在codeblocks下g++编译运行结果为:8 16 24. 在vc6.0下编译运行结果为:8 20 32. 能够分析出codeblocks下的结果是本类加上父类的结果。vc下是 本类加父类后又加了4个字节。 但是这段代码: #include<iostream> using namespace std; class A { public: virtual void a(){}; }; class B:public virtual A { public: virtual void b(){}; }; class C:public virtual B { public: virtual void c(){}; }; int main() { cout<<sizeof(A)<<endl; cout<<sizeof(B)<<endl; cout<<sizeof(C)<<endl; } codeblocks下编译运行结果为 4 4 4. vc下编译运行结果为:4 12 20. 从结果来看,vc下是 本类加父类后又加了4个字节。而codeblocks结果就不再是本类加父类的结果(这个有点迷茫)。 我只能提供这么多信息了~ 如果你有更好的解释可以给我留言,相互学习~

    赞(13)

    回复(0)

    评论

  • miaomiao342874 2017-10-03 00:00:00
    虚函数表是编译器用来实现多态的方法。一般来说,虚函数表是一个数组,数组的元素是虚函数的指针。每个对象都会有一个虚函数表,当在某个对象上调用虚函数时,通过查询这个表来获得继承层次中到底哪个函数被实际调用。 对于一个类如果有虚函数,就会在这个类中创建一个虚表,也就会产生一个虚指针指向这个虚表。 既然有一个指针指向了虚表,这个类派生后,在派生类中就不必再创建虚表,如果派生类还有自己的虚函数,那么只在派生类中创建该虚函数的一个虚表,产生一个指向该虚表的指针。 为每个类设置虚表,初始化虚指针,为虚函数调用插入代码都是自动发生的,不必担心这些。 (我看到过虚继承下虚表问题的分析,直接继承下没看过,特此又分析了一下,修改) #include<iostream> using namespace std; class A { public: virtual void a(){}; }; class B:public virtual A { public: virtual void b(){}; }; int main() { cout<<sizeof(A)<<endl; cout<<sizeof(B)<<endl; } 对于这个程序,你大概是在vc6.0下运行的吧,在vc下结果是4和12。我用的编译器是g++,对于这段程序的结果确实都为4. 因编译器不同导致结果不同这个我倒是没注意,这样可以得出,对虚函数这里的处理机制和编译器也是有关的,g++编译器还是更符合新的标准。 把虚继承virtual去掉再运行,在codeblocks下,g++编译运行结果都为4. vc下编译运行结果也都为4. 在分析一个例子: #include<iostream> using namespace std; class A { char j[3]; public: virtual void a(){}; }; class B:public A { char k[3]; public: virtual void b(){}; }; class C:public B { char m[3]; public: virtual void c(){}; }; int main() { cout<<sizeof(A)<<endl; cout<<sizeof(B)<<endl; cout<<sizeof(C)<<endl; } 这个直接继承的例子,在vc下,codeblocks下结果都为 8 12 16. 再看这个直接继承的例子: #include<iostream> using namespace std; class A { public: virtual void a(){}; }; class B:public A { public: virtual void b(){}; }; class C:public B { public: virtual void c(){}; }; int main() { cout<<sizeof(A)<<endl; cout<<sizeof(B)<<endl; cout<<sizeof(C)<<endl; } vc下河codeblocks下结果都为 4. 这两个程序说明,直接继承下,输出结果应当是本类所占的字节加父类数据成员所占字节,父类的虚指针所占字节没有加上。 加入虚继承后: #include<iostream> using namespace std; class A { char j[3]; public: virtual void a(){}; }; class B:public virtual A { char k[3]; public: virtual void b(){}; }; class C:public virtual B { char m[3]; public: virtual void c(){}; }; int main() { cout<<sizeof(A)<<endl; cout<<sizeof(B)<<endl; cout<<sizeof(C)<<endl; } 这段代码,在codeblocks下g++编译运行结果为:8 16 24. 在vc6.0下编译运行结果为:8 20 32. 能够分析出codeblocks下的结果是本类加上父类的结果。vc下是 本类加父类后又加了4个字节。 但是这段代码: #include<iostream> using namespace std; class A { public: virtual void a(){}; }; class B:public virtual A { public: virtual void b(){}; }; class C:public virtual B { public: virtual void c(){}; }; int main() { cout<<sizeof(A)<<endl; cout<<sizeof(B)<<endl; cout<<sizeof(C)<<endl; } codeblocks下编译运行结果为 4 4 4. vc下编译运行结果为:4 12 20. 从结果来看,vc下是 本类加父类后又加了4个字节。而codeblocks结果就不再是本类加父类的结果(这个有点迷茫)。

    赞(10)

    回复(0)

    评论

获取验证码
我已经阅读并接受《仪器网服务协议》

热门问答

C++虚表问题
请教一个问题,C++中从虚基类派生出来的类,如果原虚基类中的虚函数在该类中还是虚函数,那么系统会不会给这个派生类创建虚表?或者是只分配一个指针指向diyi次出现这些虚函数的基类的... 请教一个问题,C++中从虚基类派生出来的类,如果原虚基类中的虚函数在该类中还是虚函数,那么系统会不会给这个派生类创建虚表?或者是只分配一个指针指向diyi次出现这些虚函数的基类的虚表? 1楼的朋友谢谢你的回答 我喜欢结交你这样的有研究精神的朋友,你的分析很有研究价值,暂且先不讨论编译器的问题。 我从深入浅出MFC中找到虚表的相关知识,这个肯定不会有错,期待问题能够尽早彻底解决 深入浅出MFC: 1.每一个内涵虚函数的类,编译器都为它做出一个虚拟函数表,表中的每一个元素都指向一个虚函数的地址。 此外,编译器当然也会为类表加上一项成员函数,是一个指向该虚拟函数表的指针(常被称为vptr),每一个由此类别派生出来的类,都有这么一个vptr。 2.虚表以及这种间接呼叫方式。虚表的内容是依据类别中的虚函数声明次序--填入函数指针。派生类别会继承基础类别的虚表(以及所有其他可以继承的成员),当我们在派生类中改写虚函数时,虚表就受了影响;表中的元素所指的函数地址将不再是基类的函数地址,而是派生类的函数地址。 总结:通过深入浅出MFC的内容可以得知: 1,派生类要继承基类的虚表,而不只是说继承基类的虚表指针,所以可以判定,至少从理论上可以判定虚表是要拷贝的,而不是继续用父类虚表,而且多想想也应该可以理解,父类对象指针所指的虚表内容应该和子类不同,因为刚才有提到虚表函数的重定向。可能编译器做了某种优化,再研究 展开
2017-10-02 03:59:31 369 2
继电器虚亮需接的问题
我的配电柜有些继电器总是出现虚亮虚接的问题。现场的开关分明已断开,但是对应的继电器虚亮,对应的PLC上的点返回信号还有。这路开关信号是用一个2芯线拉过来的,长度大约有300来米,是有干扰造成的吗。请各位大师多多指教!
2012-05-11 17:59:37 442 1
百事得380p电源是虚表的吗?
装机那个js什麽键都是Z低端的(连个电源在造假,我这辈子不上他那去了)
2014-06-14 06:46:46 438 2
虚短路与虚断路有区别吗
 
2010-09-27 10:45:12 745 2
虚的组词
 
2011-02-04 01:04:23 348 3
虚拟与现实结合
虚拟与现实结合是什么技术?... 虚拟与现实结合是什么技术? 展开
2016-11-09 01:52:44 315 2
压力表、真空表读数问题
现有一个压力真空表,刻度范围为-0.1,0,0.1,……0.5,另有一个表刻度范围为-0.1,0,0.02,0.04,……0.08,请问这两种刻度上,每一个读数都代表实际压力是多少?... 现有一个压力真空表,刻度范围为-0.1,0,0.1,……0.5,另有一个表刻度范围为-0.1,0,0.02,0.04,……0.08,请问这两种刻度上,每一个读数都代表实际压力是多少? 展开
2009-09-22 00:32:09 365 3
功率因数表接线问题,求助
 
2017-06-18 05:23:14 333 1
Microsoft Visual C++
program:G\新建文件\轮廓仪\WXZ_8316_1.exe file:bardock.cpp line:709 for information on how your program can cause an assertion railure,see the visual C++ documentation on asserts. (press retry to debug the application) 这是什么错误啊,... program:G\新建文件\轮廓仪\WXZ_8316_1.exe file:bardock.cpp line:709 for information on how your program can cause an assertion railure,see the visual C++ documentation on asserts. (press retry to debug the application) 这是什么错误啊,如何调试。 展开
2015-07-05 13:09:59 378 1
计时器c++程序
2017-11-28 03:11:16 204 1
如果知道了页表寄存器的地址和虚页号,如何知道PTE的地址?
例如知道页表寄存器地址是0x20000,知道虚页号是0x6EE1,那这个PTE地址应该是什么?有一个9bit的页偏量... 例如知道页表寄存器地址是0x20000,知道虚页号是0x6EE1,那这个PTE地址应该是什么? 有一个9bit的页偏量 展开
2018-12-09 06:46:13 757 0
求c++简易计时器
采用dev-c++编译环境,越简易越好,只需从循环开始开始计时,x秒后执行另一指令,计时器清零,重新计时,再执行同一指令,如此反复,直至循环结束即可,高手解答,万分感谢,高分悬赏!
2011-02-10 11:29:06 483 2
c++程序测试目的?
 
2012-07-16 01:14:46 319 4
死神虚篇的结局是什么
 
2014-01-17 15:58:04 209 2
什么是虚焊?虚焊形成的原因以及检测方法---徕深科技

    虚焊是焊点处只有少量的锡焊住,看上去焊好了,实际上未能完全融合,造成接触不良,时通时断。,虚焊是常见的一种线路故障,有两种, 一种是在生产过程中的,因生产工艺不当引起的,时通时不通的不稳定状态; 另外一种是电器经过长期使用,一些发热较严重的零件,其焊脚处的焊点极容易出现老化剥离现象所引起的。 


虚焊常见种类

1.虚焊点产生在焊点中间

    这类现象经常出现在工作温度比较高的元件周围。产生的原因主要是因为焊点处用锡量比较少.焊接温度太高(加速氧化)或太低,造成焊接质量差。这种焊点周围会有一圈比较明显的塌陷,且焊点不光滑,焊点颜色呈暗灰,因此相对来说,还是比较容易发现的。

2.虚焊部位在焊点与焊盘之间

    产生这种虚焊现象的原因是虽然元件引脚处理得好,但线路板敷铜焊盘面上没有处理好,导致焊接时吃锡不充分造成的。这种虚焊现象由于隐藏在焊点下面,一般不容易发现。

3.焊点在元件引脚与焊点之间

    产生的原因主要是元件引脚没有得到较好的处理,导致引脚与焊点不能很好地熔合。日久后元件引脚氧化现象加剧,形成时通时不通的接触不良现象。

虚焊产生的原因

1.焊盘设计有缺陷;

2.助焊剂的还原性不良或用量不够;

3.被焊接处表面未预先清洁好,镀锡不牢;

4.烙铁头的温度过高或过低,表面有氧化层;

5.焊接时间太长或太短,掌握得不好;

6.焊接中焊锡尚未凝固时,焊接元件松;

7.元器件引脚氧化;

8.焊锡质量差。

虚焊的检测方法

1.直观检查法

    一般先寻找发热的元器件,如功率管、大电流二极管、大功率电阻、集成电路等,这些元件因为发热容易出现虚焊,严重的直接可以看出,轻微的可以用放大镜观看。一般刚焊好的引脚是很光润的。当边缘受到影响时,由于不断地挤压和拉伸,会变得粗糙无光泽,焊点周围就会出现灰暗的圆圈,用高倍放大镜看可以看到龟裂状的细小的裂缝群,严重时就形成环状的裂缝,即脱焊。所以,有环状黑圈的地方,即使没有脱焊,将来也是隐患。大面积补焊集成电路、发热元件引脚是解决的方法之一。

2.电流检测法

    检查电流设定是否符合工艺规定,有无在产品负载变化时电流设定没有相应随之增加,使焊接中电流不足而产生焊接不良。

3.晃动法

就是用手或摄子对低电压元件逐个地进行晃动,以感觉元件有无松动现象,这主要应对比较大的元件进行晃动。另外,在用这种方法之前,应该对故障范围进行压缩.确定出故障的大致范围,否则面对众多元件。逐个晃动是很不现实的。

4.震动法

    当遇到虚焊现象时,可以采取敲击的方法来证实,用螺丝刀手炳轻轻敲击线路板,以确定虚焊点的位置。但在采用敲击法时,应保证人身安全,同时也要保证设备的安全,以免扩大故障范围。

5.补焊法

    补焊法是当仔细检查后仍旧不能发现故障时进行的一种维修方法,就是对故障范围内的元件逐个进行焊接。这样,虽然没有发现真正故障点,但却能达到维修目的。



2019-07-17 16:59:24 957 0
急!!!关于质量流量计,一次表,二次表,485通讯模块的问题
哪位大侠懂的话加QQ谈,多谢!494766868... 哪位大侠懂的话加QQ谈,多谢! 494766868 展开
2012-10-23 22:31:31 358 1
C/C++开源即时通讯软件
 
2007-10-11 01:26:43 327 1
C++和组态软件哪个好
 
2013-10-21 19:08:11 307 1
在哪可以下载C++编程软件
 
2015-10-12 01:56:24 299 3
怎么用红外热像仪检测虚焊、???
如题,电路板虚焊问题严重,怎么用热像快速的检测虚焊
2014-06-10 01:47:03 390 2

9月突出贡献榜

推荐主页

最新话题