c++类的成员函数存储方式(是否属于类的对象)---一道面试题引发的思考
来源:互联网 发布:条形码扫描软件 编辑:程序博客网 时间:2024/04/28 08:18
昨天去面试一家公司,面试题中有一个题,自己没弄清楚,先记录如下:
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,再去找虚地址指针,肯定是不允许的)。
下面具体分析一下吧
先看一下类的成员函数的情况,
class A{};class B{public:B(){}~B(){}};class C{public:C(){}virtual ~C(){}};
类A、B、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的比较可以看出成员函数是不占用类空间的,再具体一个例子:
class E{public:E(){}~E(){}private:int m_data;char c;};
sizeof(E)在32位机器上输出结果,如果不考虑对齐 为5,考虑则为8,可见和上面B类的预期一致。
我们可以说,静态数据成员和静态成员函数时类的一部分,而不是对象的一部分(谭老师说的)。
当我们实例化一个对象的时候,因为这个对象是用类定义的,那么它理所当然拥有了这个类的数据和函数。但是,一般情况下,不同的对象,他们的的数据值不同,但是函数的代码都相同。所以,为了节约存储空间(想象一下我们如果定义了100个对象,那么用100段内存空间存储相同的代码,岂不是很浪费?),我们让成员函数的代码共享。我们把成员函数的代码存储在对象空间之外。换句话说,成员函数的代码,都不占据对象的存储空间。它会被存在其他地方。
所以类的成员函数,对于类来讲。一方面是逻辑上的“属于”,一方面是物理上的“不依赖“。
回到思考题上来,对于非静态成员函数来说,它当然是对象的一部分。(只是因为存储方式上的特殊性,容易让人误解!)
类中包括成员变量和成员函数
new出来的只是成员变量,成员函数始终存在
所以如果成员函数未使用任何成员变量的话,不管是不是static的,都能正常工作
一个对象的空间=所有成员变量的大小
如果这个对象的类有虚函数的话,还可能多一个指向虚表的指针
所有函数存放在独立于对象的存储空间内
对象调用函数时,对静态成员函数直接调用不存在问题,对成员函数需要把自己以this指针传给函数以指明以哪个对象调用
所以用未初始化的指针调用静态成员函数、或者调用未使用任何成员变量的成员函数(即未用到this指针)
从理论上都是可行的,至于具体支不支持看各个编译器吧
思考:
main函数中,如果
D d;//=NULL;
d.printA();
d.printB();
调用呢?
都能正常输出,d在栈上。。。
- c++类的成员函数存储方式(是否属于类的对象)---一道面试题引发的思考
- (转)c++类的成员函数存储方式(是否属于类的对象)---一道面试题引发的思考
- C++:类的成员函数存储方式(是否属于类的对象)
- c++类的成员函数、数据成员存储方式(是否属于类的对象)
- 一道C面试题引发的思考
- C++类的成员函数存储方式(是否属于类的对象)
- 类的成员函数存储方式(是否属于类的对象)
- 由一道面试题引发的思考
- 百度一道面试题引发的思考
- 一道面试题引发的思考
- 一道360面试题引发的思考
- 一道360面试题引发的思考
- 一道面试题引发的思考
- 一道面试题引发的思考
- 一道js面试题引发的思考
- 一道面试题引发的思考
- (续)一道面试题引发的思考
- 一道 JS 面试题引发的思考
- 改变工作表背景(3)
- Flex 广西水利网 界面设计
- 二手儿童用品交易平台Kidizen
- C#通过接口与线程通信(捕获线程状态)介绍
- 简单的使用exec函数
- c++类的成员函数存储方式(是否属于类的对象)---一道面试题引发的思考
- 【Android基础】listview控件的使用(3)------Map与SimpleAdapter组成的多显示条目的Listview
- UVA 11795 - Mega Man's Mission(状态压缩dp)
- spring用gradle导入eclipse时异常导致失败
- android顶部导航条
- 简单的01背包!!
- 改变工作表背景(4)
- Drawable资源---使用原始资源
- C#图像的灰度化处理:提取像素法介绍