c++内存模型的问题,应该一百个人只有一个能答上来的

bigblacktree1 2016-09-01 11:32:34
抱歉哈,标题只是为了吸引关注。。。

// Test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;
class Father
{
public:
virtual void MyFunc()
{
cout<<"this is f"<<endl;
}

void TestFunc() {cout<<"this is TestFunc"<<endl;}
};
class Children : public Father
{
public:
virtual void MyFunc()
{
cout<<"this is c"<<endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Children c;
c.Father::MyFunc();
getchar();
return 0;
}
问题:
1、请说出输出是什么
2、这里该怎么理解c.Father::MyFunc();
3、按照书上说的c++内存模型,如果子类重写父类的虚函数,那么子类的虚表vtbl中的MyFunc函数应该被覆盖了,那么为什么通过子类还能调用到父类的这个虚函数呢。
题外话:
1、类Father有虚函数还有普通成员函数,定义他的对象之后,可以通过对象的地址来间接调用虚函数(程序如下),但是如何调用成员函数TestFunc呢?
typedef void(*Fun)(void);
Father f;
Fun pFun = NULL;
pFun = (Fun)*((int*)*(int*)(&f));
pFun();
...全文
236 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
lm_whales 2016-09-03
  • 打赏
  • 举报
回复
成员函数指针,可以间接调用非静态成员函数 class C{ public : void fun(){} }; void (C ::*p)() =&C::fun; C obj,&ref=obj,*ptr=&obj; (obj.*p)(); (ref.*p)(); (ptr->*p)(); 至于让他通过普通函数指针调用成员函数 因为不同编译器的(可能不同平台也不同哦),对非静态成员函数处理不同 需要针对具体编译器,采用某种技巧 这个不是,C,C++本身可以直接支持的,不是可移植的。
尚书左仆射 2016-09-03
  • 打赏
  • 举报
回复
输出是:this is f 虚函数表的覆盖只是把子类虚函数表中的相应虚函数的地址覆盖了,并不是把对应的虚函数实现覆盖,父类的虚函数还是在内存中的。 然后,你调用的方式是显示调用虚函数,这个时候是静态决议,所以调用的是父类的虚函数。
bigblacktree1 2016-09-03
  • 打赏
  • 举报
回复
谢谢大家的回复,不过后两个问题似乎还是不明白,没人回答啊
ForestDB 2016-09-03
  • 打赏
  • 举报
回复
1、请说出输出是什么 应该是 cout<<"this is f"<<endl; 2、这里该怎么理解c.Father::MyFunc(); c有两个成员函数: Father::MyFunc()和Children::MyFunc(); 这里是想要调用Father::MyFunc()而已 3、按照书上说的c++内存模型,如果子类重写父类的虚函数,那么子类的虚表vtbl中的MyFunc函数应该被覆盖了,那么为什么通过子类还能调用到父类的这个虚函数呢。 这里跟“覆盖”没有半点关系,你甚者可以把virtual都去掉; 所谓的“覆盖”,virtual是第一步,重写是第二步,“用指向基类的指针或者引用来调用虚函数”,这是第三步,你没有走到第三步,所以就不是覆盖,也跟虚表什么的没关系。 跑之前先学会走,走之前先学会爬。
fefe82 2016-09-03
  • 打赏
  • 举报
回复
1、请说出输出是什么 this is f 2、这里该怎么理解c.Father::MyFunc(); C++: 显式调用父类的 MyFunc 3、按照书上说的c++内存模型,如果子类重写父类的虚函数,那么子类的虚表vtbl中的MyFunc函数应该被覆盖了,那么为什么通过子类还能调用到父类的这个虚函数呢。 3.1 这东西应该不叫C++内存模型吧 3.2 没看过你那本的书,不知道怎么写的 3.3 虚表被覆盖了,但是可以不通过虚表调用啊 题外话: 1、类Father有虚函数还有普通成员函数,定义他的对象之后,可以通过对象的地址来间接调用虚函数(程序如下),但是如何调用成员函数TestFunc呢? typedef void(*Fun)(void); Father f; Fun pFun = NULL; pFun = (Fun)*((int*)*(int*)(&f)); pFun(); 这种 hack 虚表的方式都是编译器相关的。虚表不是 C++ 的一部分,这是编译器实现虚函数常用的一种方式。具体用不用虚表,以及虚表的具体实现细节,各个编译器都可能不同。 如果不是虚函数,它的地址可能并没有被存储到任何地方。
赵4老师 2016-09-02
  • 打赏
  • 举报
回复
《深度探索C++对象模型》 《C++反汇编与逆向分析技术揭秘》
lm_whales 2016-09-02
  • 打赏
  • 举报
回复
C++实现多态,是通过特定方式实现的 直接用函数名的话 1)显式方式 就是引用和指针 加函数名 2)隐式方式就是 在非静态成员函数内(构造,析构函数,除外),直接用函数名,调用函数 另外,通过成员函数指针方式,也可以, 这是更加间接隐蔽的方式。 类名调用方式,不能实现多态。 。。。。。。。。。。。。。。 函数调用方式,不影响对象内部结构 也不影响,函数的重载和重写 只是,不同调用方式,实现不同功能。 效果不一致而已。
lm_whales 2016-09-02
  • 打赏
  • 举报
回复
C++直接调用成员函数,有2大类方式 1)类名调用,用类名调用函数(静态或者非静态) 1.1)C::fun(); //这种跟多态无关,无论虚函数,非虚函数,直接调用 1.2) 对象类名联合调用
      C obj,&ref =obj,*ptr=&obj;
          obj.C::fun();
          ref.C::fun();
          ptr->C::fun();
//这种跟多态无关,无论虚函数,非虚函数,直接调用 2)对象调用方式 2.1)直接用对象调用
C obj;
        obj.fun();       //这种,都是编译为直接调用函数,跟多态无关
2.2)通过引用调用
    C obj;
         C &ref=obj;
         ref.fun();   //这种方式调用虚函数,可以显式实现多态
                         //非虚函数,则编译为直接调用函数,不是实现多态的途径
2.3)通过指针调用
 C obj;
        C* ptr =&obj;
         ptr->fun(); //和引用相同。/这种方式调用虚函数,可以显式实现多态
                         //非虚函数,则编译为直接调用函数,不是实现多态的途径
在类的成员函数内部: 类的非静态成员函数内部 fun(), 只有函数名调用函数, fun()相当于 this->fun(); 带类名 C::fun();相当于 this->C::fun(); 类的静态成员函数,类外部函数,调用 只有 静态函数,可以直接调用 fun () 相当于 C::fun(); 非静态成员函数,必须通过对象调用,obj.fun(),或者 obj.C::fun(); ref.fun(),或者 ref.C::fun() ptr->fun();ptr->C::fun(); 直接用函数名,调用非静态成员函数(不显式通过对象,指针,引用,类名): a)构造函数,析构函数 内直接调用非静态成员函数(不显式通过对象,指针,引用),都是编译为直接调用函数 这其实跟 this->C::fun() ;相同 b)其他非静态函数内部,只有函数名调用函数, fun()相当于 this->fun(); 这种情况,可以隐式实现多态。
张小飞Official 2016-09-02
  • 打赏
  • 举报
回复
依旧是覆盖,但是并不代表父类的函数不在了,父类的函数还是在的 顺便说一句,你的第三个问题应该是问错了,是父类的被覆盖了而不是子类。
sdghchj 2016-09-02
  • 打赏
  • 举报
回复
子类的虚表vtbl中的MyFunc函数地址被改成了指向子类的该虚函数地址,父类的该虚函数依然存在,c.Father::MyFunc();就是不通过子类的vtbl去调用,直接去调用父类的函数。 f.TestFunc()
dustpg 2016-09-02
  • 打赏
  • 举报
回复
显式调用虚函数而已.....就是当作普通的函数调用, 编译/链接 时确定了函数
碎炎 2016-09-02
  • 打赏
  • 举报
回复
引用 6 楼 zhao4zhong1 的回复:
《深度探索C++对象模型》 《C++反汇编与逆向分析技术揭秘》
同意 我觉得第二本书很好 从汇编角度剖析了c++的实现 能读懂的话 对c++的理解会上一个档次

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧