昨天去面试一家公司,面试题中有一个题,自己没弄清楚,先记录如下:

class D
{
public:
void printA()
{
cout<<"printA"<<endl;
}
virtual void printB()
{
cout<<"printB"<<endl;
}
};

main函数调用:

D *d=NULL;
d->printA();
d->printB();

输出结果是?

当时想的是对象d直接初始化为NULL,非虚的成员函数没有地址,应该找不到,而virtual成员函数,由于对象会有指向虚拟函数表的指针-vptr,指向virtual函数列表的虚拟函数表,这样应该能够取到地址(实际上,这个virtual函数的printB最应该想到是直接崩溃,因为d指向NULL,即地址为0x00000000,再去找虚地址指针,肯定是不允许的)。

下面具体分析一下吧

先看一下类的成员函数的情况,

 

类A、B、C三个类,一个是什么都没有的真的空类,一个是有成员函数的类,最后一个是带有虚函数的类。

class A
{ };
class B{
public:
B(){}
~B(){}
};
class C
{
public:
C(){}
virtual ~C(){}
};

那他们分别咱的内存大小是多少呢?

cout<<"A="<<sizeof(A)<<endl;
cout<<"B="<<sizeof(B)<<endl;
cout<<"C="<<sizeof(C)<<endl;

32位windows xp机器上测试结果:

A=1

B=1

C=4

从A和B的比较可以看出成员函数是不占用类空间的,再具体一个例子:

sizeof(E)在32位机器上输出结果,如果不考虑对齐 为5,考虑则为8,可见和上面B类的预期一致。

我们可以说,静态数据成员和静态成员函数时类的一部分,而不是对象的一部分(谭老师说的)。

当我们实例化一个对象的时候,因为这个对象是用类定义的,那么它理所当然拥有了这个类的数据和函数。但是,一般情况下,不同的对象,他们的的数据值不同,但是函数的代码都相同。所以,为了节约存储空间(想象一下我们如果定义了100个对象,那么用100段内存空间存储相同的代码,岂不是很浪费?),我们让成员函数的代码共享。

我们把成员函数的代码存储在对象空间之外。换句话说,成员函数的代码,都不占据对象的存储空间。它会被存在其他地方。

所以类的成员函数,对于类来讲。一方面是逻辑上的“属于”,一方面是物理上的“不依赖“。

回到思考题上来,对于非静态成员函数来说,它当然是对象的一部分。(只是因为存储方式上的特殊性,容易让人误解!)

回答开头问题:

类中包括成员变量和成员函数
new出来的只是成员变量,成员函数始终存在
所以如果成员函数未使用任何成员变量的话,不管是不是static的,都能正常工作

一个对象的空间=所有成员变量的大小

如果这个对象的类有虚函数的话,还可能多一个指向虚表的指针

所有函数存放在独立于对象的存储空间内
对象调用函数时,对静态成员函数直接调用不存在问题,对成员函数需要把自己以this指针传给函数以指明以哪个对象调用

所以用未初始化的指针调用静态成员函数、或者调用未使用任何成员变量的成员函数(即未用到this指针)
从理论上都是可行的,至于具体支不支持看各个编译器吧

思考:

main函数中,如果

D d;//=NULL;
    d.printA();
    d.printB();

调用呢?

都能正常输出,d在栈上。。。

(转)c++类的成员函数存储方式(是否属于类的对象)---一道面试题引发的思考的更多相关文章

  1. C++:类的成员函数定义方式

    1.成员函数的第一种定义方式:在类声明中只给出成员函数的原型,而将成员函数的定义 放在类的外部. 返回值类型 类名::成员函数名(参数表) {      函数体  } class Point{ pub ...

  2. C++中静态成员函数和普通成员函数存储方式相同

    先从一个示例查看类的创建过程中,静态成员函数和普通成员函数的存储区别. #include "stdafx.h" #include<iostream> #include& ...

  3. C++编译器是如何管理类和对象的,类的成员函数和成员变量

    C++中的class从面向对象理论出发,将变量(属性)和函数(方法)集中定义在一起,用于描述现实世界中的类.从计算机的角度,程序依然由数据段(栈区内存)和代码段(代码区内存)构成. #include ...

  4. C++类的成员函数使用的一些小总结

    From: http://blog.csdn.net/xiayefanxing/article/details/7607506 这一阵做项目代码开发的时候,用到了在一个C++文件中使用另一个类的成员函 ...

  5. 关于C++类的成员函数是否要加关键字“const”

    原则:类的成员函数在小括号后大括号前加上 const ,代表不准备改变对象的数据.不加的话代表有可能会改变对象的数据. 1.当常量对象,就是加上const修饰的类的成员去调用常量成员函数时,这表示:对 ...

  6. C++学习之路—运算符重载(二)运算符重载作为类的成员函数和友元函数

    (根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 对运算符重载的函数有两种处理方式:(1)把运算符 ...

  7. 类的成员函数指针和mem_fun适配器的用法

    先来看一个最简单的函数: void foo(int a) { cout << a << endl; } 它的函数指针类型为 void (*)(int); 我们可以这样使用: v ...

  8. Python类变量与实例变量及成员函数修饰方式说明(与Java定义方式进行类比)

    Python类中的变量有类变量和实例变量之分. 类变量:变量绑定在类上,同一个类之间的共享变量,类比于Java中的静态变量static 公有变量定义 Java 的定义方式 class Test{ pu ...

  9. C++点滴----关于类常成员函数

    关于C++中,类的常成员函数 声明样式为:   返回类型 <类标识符::>函数名称(参数表) const 一些说明: 1.const是函数声明的一部分,在函数的实现部分也需要加上const ...

随机推荐

  1. 【iOS】编译静态库

    与java和.net一样,objc也由类库的概念,不过在在objc上一般叫库,库表示程序代码集合,可以共享给其他程序使用,库是编译后的二进制文件,因此不能看到源代码,多用于一些开放sdk(如百度地图s ...

  2. C#强力粉碎文件代码分享,升级中用到

    360的文件粉碎机还是很强大的,在我们客户端winform升级的时候,必须将有些文件进行强力删除后下载更新,如果删除失败很有可能整个 程序就无法更新到最新的版本,所以这里参考了网上的资料整理了一个文件 ...

  3. Hibernate关联映射及高级查询

    一.Hibernate中的关联关系 1.1.单向一对多关联关系 按照以下步骤配置hibernate中持久化类的一对多对象关联: (1).持久化类添加关联类的相关属性及getter/setter方法. ...

  4. ahjesus linux连接阿里云ubuntu服务器并更改默认账号和密码,以及创建子账户

    先确保本地Linux服务器SSH服务开启,如果没有开启直接执行指令:service sshd start 然后我们使用ssh指令进行远程登陆 ssh username@ip-address 输入pas ...

  5. [.NET] SQL数据分页查询

    [.NET] SQL数据分页查询 程序下载 范例下载:点此下载 原始码下载:点此下载 NuGet封装:点此下载 数据查询 开发系统时,使用C#执行SQL查询指令,就可以从SQL数据库里查询所需数据. ...

  6. Exchange 2013 、Lync 2013、SharePoint 2013 二

    上一篇简单介绍了安装过程,本篇主要集成 上一篇文章有关于头像的显示问题,engineer  给出了一个连接,介绍了Exchange和Lync的集成过程,根据介绍都配制了一遍. 一.Exchange 和 ...

  7. js判断客户端平台

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. JS数组的forEach方法(兼容所有浏览器)

    //->自己在内置类的原型上扩展一个myForEach来处理forEach不兼容的问题//callBack:回调函数,遍历数组中的一项,就要执行一次callBack//context:改变cal ...

  9. JS-取出字符串中重复次数最多的字符并输出

    /** 取出字符串中重复字数最多的字符 */ var words = 'sdfghjkfastgbyhnvdstyaujskgfdfhlaa'; //创建字符串 var word, //单个字符 le ...

  10. 常用 windows运行命令

    winver---------检查Windows版本 wmimgmt.msc----打开windows管理体系结构(WMI) wupdmgr--------windows更新程序 wscript--- ...