Virtual Member Functions & Static Member Function

如果一个 normalize() 是一个 virtual member function, 那么以下的调用:

ptr->normalize();

将会被内部转化为:

(*ptr->vptr[1])(ptr);

其中:
vptr 表示由编译器生成的指针, 指向 virtual table, 它被安插在每一个声明有(或继承自) virtual functinos 的 class object 中。 事实上其名称也会被 mangled, 因为在一个复杂的 class 派生体系中, 可能存在多个 vptrs。
1 是 virtual table 的索引值, 关联到 nirmalize 函数。
第二个 ptr 表示 this 指针。
类似的道理, 如果 magnitude() 也是一个 virtual function,它在 normalize() 中的调用操作将被转化如下:

//register float mag = magnitude();
register float mag = (*this->vptr[2] )(this);

此时, 由于 Point3d::magnitude() 是在 Point3d::normalize() 中被调用, 而后者已经由虚拟机制而决议妥当, 所以明确地调用 Point3d 实体会比较有效率, 并因此压制由于虚拟机制而产生的不必要的重复调用操作:

//明确的调用操作(explicit invocation) 会压制虚拟机制
register float mag = Point3d::magnitude();

如果 magnitude() 声明为 inline 函数会更有效率。使用 class scope operator 明确调用一个 virtual function, 其决议方式会和 ninstatic member functino 一样:

register float mag = magnitude__7Point3dFv(this);

对于以下调用:

//Point3d obj;
obj.normalize();

如果编译器把它转换为:

(*obj.vptr[1])(&obj);

虽然语意正确, 却没有必要, 因为经由 obj 调用的函数实体只可以是 Point3d::normalize() 经由一个 class object 调用一个 virtual function,这种操作应该总是被编译器像对待一般的 nonstatic member function 一样的加以决议:

//因为 normalize() 的归属无可争议
normalize__7Point3dFv(&obj);

这项优化工程的另一个利益是 virtual function 的一个 inline 函数实体可以被扩展开来, 因而提供极大的效率意义。

Static Member Function
如果 Point3d::normalize() 是一个 staitc member function, 以下两个操作:

obj.;normalize();
ptr->normalize();

将被转为一般的 nonmember 函数调用, 像这样:

//obj.normalize()
normalize__7Point3dFv();
//ptr->normalize__7Point3dFv();

在 C++ 引入 static member function 之前, 我想你很少看到下面这种怪异写法:

((Point3d*) 0 )->object_count();

其中的 object_count() 只是简单传回 _object_cout 这个 static data member. 这种习惯是如何演化来的呢?
在引入 static member function 之前, C++ 要求所有的 member functions 都必须 经由该 class object 来调用, 而实际上, 只有当一个或多个 nonstatic data members 在 member function 中被直接存取时, 才需要 class object. class object 提供了 this 指针给这种形式的函数调用使用, 这个 this 指针把在 member function 中村取得 nonstatic class member 绑定于 object 内对应的 members 之上, 如果没有任何一个 members 被直接存取, 事实上就不需要 this 指针, 因此也就没必要通过一个 class object 来调用一个 member function.
这么一来就在存取 static data members 时产生了一些不规则性. 如果 class 的设计者 把 static data member 声明为 nonpublic, 那么他就必须提供一个或多个 member functions 来存取该 member. 因此虽然你可以不靠 class object 来 存取一个 static member, 但其存取函数却得绑定于一个 class object 之上.
独立于 class object 之外的存取操作, 在某个时候特别重要: 当 class 设计者希望支持没有 class object 存在的情况(就像前述的 object_count() 那样) 时, 程序方法上的解决之道是很奇特的把 0 强制转型为一个class 指针, 因而提出一个 this 指针实体:

//函数调用的内部转换
object_count((Point*) 0 );

至于在语言层面上的解决之道, 是由 cfront 所引入的 staticmember functions. Static member functions 的主要特性是他没有 this 指针, 以下的次要特性均源于其主要特性:
1. 它不能够直接存取其 class 中的 nonstatic members
2. 它不能够被声明为 const, volatile 后 virtual.
他不需要经由 class object 才被调用--虽然它大部分时候就是这么调用的...
member selection 语法的使用是一种符号上的便利, 它会被转化为一个直接调用操作:

if(Point3d::object_count() > 1)...

哦, 这个表达式仍然需要被评估求职

//转化, 以保存副作用
(void)Foo();

一个 static member fucntion, 当然会被提出于 class 声明之外, 并给予一个经过 mangled 的适当名称, 例如:

unsigned int
Point3d::
object_cout()
{return _object_cout;}
//会被转化为
usnign int
object_cout__5Point3dSFv()
{
    return _object_cout__5Point3d;
}

其中 SFv 表示它是个 static member function, 拥有一个空白 (void) 的参数链表(argument list).
如果取一个 static member function 的地址, 获得的将是其在内存中的位置, 也就是其地址,由于 static member function 没有 this 指针, 所以其地址的类型并不是一个指向 class member function 的指针, 而是一个 nonmember 函数指针, 也就是说:

&Point3d::object_cout();

会得到一个数值, 类型是:

usigned int (*)();

而不是:

unsigned int (Point3d::*)();

static member function 由于缺乏 this 指针, 因此差不多等于 nonmember function. 它提供了一个意想不到的好处:成为一个 callback 函数,使得我们得以将 C++ 和 C-based X Windows 系统结合, 它们也可以成功的用在线程函数身上.

时间: 2024-10-06 08:14:21

Virtual Member Functions & Static Member Function的相关文章

C++ static member functions

今天复习老师昨天讲的static member functions.总觉得这玩意儿存在真是莫名其妙,度娘之,发现网上讲的都十分不清楚.还是用Google从米国网站找到了答案. class Something { private: static int s_nValue; }; int Something::s_nValue = 1; // initializer int main() { // how do we access Something::s_nValue? } In this cas

函数的效能 & 指向 Member Functions 的指针与其效能

nonmember friend 或 nonstatic member 或 static member 函数都会被转化为相同的形式, 因此三者的效率完全相同.另外, inline member function 的效率一直是最高的(前提是简单操作), 优化后的效率更是高, 这是因为编译器会将被视为不变的表达式提到循环之外, 因此只计算一次, inline 函数不只能够节省一般函数所调用的负担, 也提供程序额外的优化机会.virtual function 和 多重继承 的效率要低于一般函数, 要再

C++对象模型——Virtual Member Functions (虚拟成员函数)(第四章)

4.2 Virtual Member Functions (虚拟成员函数) 已经看过了 virtual function的一般实现模型:每一个 class 有一个 virtual table,内含该 class 中有作用的 virtual function的地址,然后每个object有一个vptr,指向 virtual table的所在. 为了支持 virtual function机制,必须首先能够对多态对象有某种形式的"执行期类型判断法(runtime type resolution)&quo

static 和 no static Member function学习

以下是做实验的一段代码: #include <iostream> using namespace std; typedef void (*p)(); class Object { public: static void s_fun_1() { cout << "static function 1\n"; } void fun_1() {cout << "no static function 1\n";} }; typedef vo

C++ Member Functions的各种调用方式

[1]Nonstatic Member Functions(非静态成员函数) C++的设计准则之一就是:nonstatic member function至少必须和一般的nonmember function有相同的效率.也就是说,如果我们要在以下两个函数之间作选择: float magnitude3d(const Point3d* _this) {...}; float Point3d::magnitude3d() const {...}; 那么选择member function不应该带来什么额

Const member functions in C++

Recently, I've started to review and learn C++ techniques. During the learning process, I followed a learn-by-example methodology, which I consider to be very effective. From now on, I'll use this blog to explain key points and interesting topics in

转:C语言中的static变量和C++静态数据成员(static member)

转自:C语言中的static变量和C++静态数据成员(static member) C语言中static的变量:1).static局部变量        a.静态局部变量在函数内定义,生存期为整个程序运行期间,但作用域与自动变量相同,只能在定义该变量的函数内使用.退出该函数后, 尽管该变量还继续存在,但不能使用它.        b.对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值.而对自动变量不赋初值,则其值是不定的.2).static全局变量        全局变量本身就是静

C++ 之const Member Functions

Extraction from C++ primer 5th Edition 7.1.2 The purpose of the const that follows the parameter list of an ordinary member function is to modify the type of the implicit this pointer. By default, the type of this is a const pointer to the nonconst v

Reading Effictive java: static member class (SMC) and nonstatic member class(NSC)

Misunderstanding of static member class : For most programmers, comparing to SMC ,we may be more familiar with static field . so we may analogously guess how SMC works according to static field's feature. That leads to a misunderstanding.--SMC may on