前两天遇到一个挺有意思的问题:
已知有一个
class A
的实例,A
有一个函数func
,但不知道A
的具体声明和定义。 如果我们有一个A
的NULL
指针A *a = NULL
,如果调用a->func()
的话,可能会出现什么情况呢?
先不管调用空指针是否是未定义行为。我们从C++语言本身角度去考虑,这样调用是有可能不抛出异常的。
我总结了几个不同的情况,如下(Visual Studio 2012):
#include <iostream>
#include <Windows.h>
#include <exception>
using namespace std;
class A
{
public:
void func()
{
cout << "wtf?" << endl;
}
void func_this()
{
cout << "wtf: " << this->data << endl;
}
static void func_static()
{
cout << "static wtf?" << endl;
}
virtual void func_virtual()
{
cout << "virtual wtf?" << endl;
}
A():data(0){}
int data;
};
int main()
{
A *a = NULL;
a->func();
__try
{
a->func_this();
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
cout << "cannot invoke func_this" << endl;
}
a->func_static();
__try
{
a->func_virtual();
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
cout << "cannot invoke func_virtual" << endl;
}
return 0;
}
命令行输出结果为:
wtf?
cannot invoke func_this
static wtf?
cannot invoke func_virtual
####分析
我们来依次分析一下能正常运行的func()
和func_static()
:
- 调用
func()
函数时A
指针不是必须的。在编译时,A
类型已知,func()
函数指针已经可以确认了。 - 同理,调用静态函数
func_static()
也不需要实际的实例对象。
对于抛出异常的func_this()
和func_virtual()
:
func_this()
用到了this
指针,而this
在这样的情况下是NULL
,所以会抛出异常。- 而调用虚函数
func_virtual()
时,我们需要一个可用的虚函数表(vtable
)指针,但显然这个指针是拿不到的,因此抛出异常。
不过,实际开发中要尽量避免这种情况哟。
####参考