C++类的成员函数存储方式(是否属于类的对象)

今天在看TAF源码的时候,发现下面一段有趣的代码:

getSmallerProxyPrx =  Application::getCommunicator()->stringToProxy<GetSmallerPrx>(MobileAssist.JiangeSmallerServer.GetSmaller);

//此处T为GetSmallerPrx
template<class T> T stringToProxy(const string& objectName,const string& setName="")
{
    T prx = NULL;
    stringToProxy<T>(objectName, prx,setName);
    return prx;
}

//此处T为GetSmallerPrx
template<class T> void stringToProxy(const string& objectName, T& proxy,const string& setName="")
{
    //getServantProxy中new ServantProxy()并返回
    ServantProxy * pServantProxy = getServantProxy(objectName,setName);
    //将ServantProxy类型的指针强制转换为GetSmallerProxy类型的指针
    //并放入GetSmallerProxy类型的智能指针中
    proxy = (typename T::element_type*)(pServantProxy);
}

我们看一看这行代码:

proxy = (typename T::element_type*)(pServantProxy);

此处的proxy 的类型是T,具体来说就是GetSmallerPrx

(更具体的说,是taf::TC_AutoPtr < MobileAssist::GetSmallerProxy >)。

而pServantProxy的类型是ServantProxy *。

(typename T::element_type*)(pServantProxy)

将ServantProxy 类型的指针强制转换成GetSmallerProxy类型的指针,而ServantProxy是GetSmallerProxy的基类——我的第一反应是——这是非常危险的!比如如果GetSmallerProxy访问了某个ServantProxy没有的成员变量,将造成越界访问

不过事实上,上面的假设并不成立——GetSmallerProxy没有新的成员变量。

但是有新的成员函数——而事实是,子类特有的成员函数是可以正常访问的:

这是不是说明,类的成员函数并不占用类对象的内存空间(如果占用的话,此处的访问将越界)。

所以我做了一个简单的实验:

#include <iostream>

using namespace std;

class A
{
    public:
        A(){}
        ~A(){}
};

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

class C
{
    public:
        C() {}
        ~C() {}

        int add(int a, int b)
        {
            return a+b;
        }
};

int main()
{
    cout << "Size(A) = " << sizeof(A) << endl;
    cout << "Size(B) = " << sizeof(B) << endl;
    cout << "Size(C) = " << sizeof(C) << endl;
    return 0;
}

./testClassFun
Size(A) = 1
Size(B) = 8
Size(C) = 1

结论:成员函数是不占用类对象内存空间的。

一般情况下,同一个类的不同对象,共享成员函数的代码。成员函数的代码存储在对象空间之外。换句话说,成员函数的代码,都不占据对象的存储空间。所以类的成员函数,对于类来讲,一方面是逻辑上的“属于”,一方面是物理上的“不依赖”。

所以如果成员函数未使用任何成员变量的话,不管是不是static的,都能正常工作。在调用成员函数时,将this指针传给函数以指明以哪个类对象调用。

因此,前面的类型向下转换是没问题的,并不会造成越界访问~

时间: 2024-11-04 14:23:15

C++类的成员函数存储方式(是否属于类的对象)的相关文章

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

昨天去面试一家公司,面试题中有一个题,自己没弄清楚,先记录如下: class D { public: void printA() { cout<<"printA"<<endl; } virtual void printB() { cout<<"printB"<<endl; } }; main函数调用: D *d=NULL; d->printA(); d->printB(); 输出结果是? 当时想的是对象d直

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

1.成员函数的第一种定义方式:在类声明中只给出成员函数的原型,而将成员函数的定义 放在类的外部. 返回值类型 类名::成员函数名(参数表) {      函数体  } class Point{ public: void setpoint(int,int); //设置坐标点的成员函数setpoint的函数原型 int getx(); //取x坐标点的成员函数getx的函数原型 int gety(); //取y坐标点的成员函数gety的函数原型 private: int x,y; }; void P

【C/C++学院】0819-/类的成员函数与const-mutable /构造与析构/拷贝构造deletedefault以及深浅拷贝/静态成员函数成员变量类在内存的存储默认参数/友元类以及友元函数

类的成员函数与const-mutable 成员函数 Fushu.h #pragma once #include <iostream> class fushu { public: int x; int y; public: fushu(); ~fushu(); void show(); inline void showall(int x, int y);//显式内联 void setxy(int x, int y);//编译器优化,默认隐式内联 void show(int x, int y);

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

From: http://blog.csdn.net/xiayefanxing/article/details/7607506 这一阵做项目代码开发的时候,用到了在一个C++文件中使用另一个类的成员函数的问题,做个小总结. 其中有些是网上搜索的资料,因为比较分散就不一一给出出处了,请作者见谅. 1.C++如何在一个类的成员函数中调用另一个类的成员函数? 假设你想在类A里调用类B的函数int f(x),两种办法: (1)class A::B 也就是说将B定义为A的父类, 这样你就可以自然的在A里面

在类外部定义类的成员函数

#include <stdio.h> class A {    public:    int b;             void   print1 (); }; void A:: print1() //在类外部定义类的成员函数时候必须加上所属类的类名 { printf("打印"); }  void main() {             A a;    a.print1();    getchar(); }

C++成员函数存储

用类去定义对象时,系统会为每一个对象分配存储空间.如果一个类包括了数据和函数,要分别为数据和函数的代码分配存储空间. 按理说,如果用同一个类定义了10个对象,那么就需要分别为10个对象的数据和函数代码分配存储单元,如图8.4所示. 图8.4 能否只用一段空间来存放这个共同的函数代码段,在调用各对象的函数时,都去调用这个公用的函数代码.如图8.5所示. 图8.5 显然,这样做会大大节约存储空间.C++编译系统正是这样做的,因此每个对象所占用的存储空间只是该对象的数据部分所占用的存储空间,而不包括函

const修饰类的成员函数

<Effective C++>里面说,尽量使用const,const修饰变量一般有两种方式:const T *a,或者 T const *a,这两者都是一样的,主要看const位于*的左边还是右边,这里不再赘述,主要来看一下当const修饰类的成员函数时,成员函数有什么特点. 类的成员函数后面加 const,表明这个函数不会对这个类对象的数据成员(准确地说是非静态数据成员)作任何改变. 在设计类的时候,一个原则就是对于不改变数据成员的成员函数都要在后面加 const,而对于改变数据成员的成员函

C++类的成员函数的指针和mem_fun适配器的用法

一.普通函数指针 我们先来看一个最简单的函数: void fool(int a) { cout << a<< endl; } 那么它的函数指针类型为: void (*) (int) 我们可以这样测试: void (*pFunc)(int) = &foo;//这里pFunc是个指针 pFunc(123); 这样就会打印出整数123:为了简化,我们可以使用typedef: typedef void (*pFunc)(int); 这里我们要说明一下: 这里的pFunc是 返回值为

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

先来看一个最简单的函数: void foo(int a) { cout << a << endl; } 它的函数指针类型为 void (*)(int); 我们可以这样使用: void (*pFunc)(int) = &foo; pFunc(123); 这就是函数指针的基本使用.   类的成员函数   那么,对于类的成员函数,函数指针有什么不同呢? 我们观察下面的类: class Foo { public: //void (Foo::*)(int) void foo(int