成员函数调用机制
我也是新手有不妥善的地方,可以指正,我会虚心学习,废话不多说,先看一段代码
#include<iostream>
#include<string>
using namespace std;
class A
{
private:
string name;
public:
void show_A( ){
cout<<"我是普通成员函数"<<endl;
}
static void show_B(){
cout<<"我是static成员函数"<<endl;
}
void show_name(){
name = "xiaoming";
cout<<"我调用了成员变量"<<endl;
}
virtual void show_AA(){
cout<<"我是虚函数"<<endl;
}
};
int main(int argv , char *args[]) {
A *p = NULL;
p->show_A();
p->show_B();
p->show_name();
p->show_AA();
}
输出:
我是普通成员函数
我是static成员函数
Segmentation fault (core dumped)
当函数走到p->show_name();
时候程序崩掉了,说明这个函数出问题了,但是这个函数注释掉了后,还是同样的结果,那么就是说后两个函数调用出问题了,为了解决是什么原因,我们必须了解一下c++的函数调用机制;
当你这样去调用时候它实际的调用是这样的
p->show_A(); //<--main函数这样写
------------------------------------------------
show_A(p); //<--被解析成这样
------------------------------------------------
show_A(A *this) //<--原函数被解析
{
cout<<"Im is A"<<endl;
}
此时this
指针就是p
的地址,当p
为NULL
时候 this
也为NULL
,如果this
指针为NULL
那么在调用成员变量的话就会非法,这种非法是在编译时检查不出来的,只有在运行时候能显示出来。
为什么空指针可以调用成员函数,不也非法吗?
答:因为在编译过程中,成员函数的地址都被固定化,所有的对象调用的函数体都是同一个,至于为什么函数行为不同,是因为每个对象调用时候都会有this指针的隐式传入,由于每个this指针地址都不相同,所以不同对象就可以调用不同的函数。这也是为什么上面的问题在编译时候检查不出来的原因,因为编译器根本不知道你传进来的是哪个对象。
经过上面分析得出下面的结论
p->show_A();
由于在这个函数内没有利用到this
指针,所以程序执行没有错误。
p->show_B();
由于此函数为static
的,它将会舍去this
指针,所以static
函数只能访问静态成员变量,程序执行没有错误。
p->show_name();
中的name = "xiaoming"
;相当于this->name="xiaoming"
,利用到了this
指针,但是指针为NULL
,找不到name
的地址,所以崩溃。
p->show_AA();
其函数为虚函数,虚函数在调用时会使用虚函数表指针
,所以在调用时候也会导致崩溃。