我们从实验中去总结问题
测试一: virtual 函数和non-virtual函数
01.#include <stdio.h>
02.class A
03.{
04.public:
05. void function(){printf("Hello World");} //无virtual关键字
06.
07.};
08.
09.class B
10.{
11.public:
12. virtual void function(){printf("Hello World");}
13.};
14.
15.int main( )
16.{
17. A* p1 = NULL;
18. p1->function(); //正常运行
19.
20. B* p2 = NULL;
21. p2->function(); //crash,Why?
22. Return 0;
23.};
测试结果:18行正常,21行crash。
为什么18行正常,21行死机呢?
其原因是:
每一个非虚成员函数实际上都等同于一个普通的C函数,其中第一个参数为对象指针,即我们常说的this指针。例如:
上面的A的function函数实际等同于:A::Function() ç==================èFunction(A*this);
与此不同,对每一个虚成员函数的调用都是通过虚函数表的虚指针vptr来进行调用的,如上面的p2->function一句将被编译器解释为:
(* p2->vptr[1] )(p2)
很容易理解,虚函数的调用是动态决定的。也很容易理解,21行crash,18行正常。很显然,如果在A类的成员函数function里,有去使用成员变量,该函数同样会crash.
我们再来看看测试二:关于C++ static 成员函数
#include"stdio.h"
#include"stdafx.h"
#include<stdio.h>
class A
{
public:
void function(){ printf("Hello World");}
static A* instance();
A();
};
static A *Test1 =NULL;
A::A()
{
Test1 = this;
}
A* A::instance()
{
return Test1;
}
int main( )
{
A *StackObj = new A;
delete StackObj;//Don’t set it to null intentionally….
while(StackObj && StackObj->instance() )
{
printf("Error--->%d.\n",StackObj);
}
return 0;
};
Static函数没有this指针,可以认为他就是普通的c函数。
普通的c函数编译器都是通过name mangling技术,来对函数加以区分:
StackObj->instance()等同于:ZN1A8instanceEv()
备注:
①事实上编译器为了避免函数重载造成的重名情况,会对函数的名字进行处理,使之成为独一无二的名称。 (name mangling技术)
②将成员函数声明为static,可以使成员函数不经由this指针便可调用。
③vptr表中,索引号0为类的type_info。
一叶知秋:“安全“的野指针、 static函数、成员函数、this 指针、gcc编译器、name mangling
最新推荐文章于 2025-05-03 06:58:41 发布