虚成员函数(虚函数) 静态成员函数调用方式
class Myclass{
public:
int i;
void myfunc(int abc){
i += abc;
}
virtual void myvirfunc(){
printf("myvirfunc()被调用 this = %p\n ", this);
}
}
int main(){
Myclass mcls; // 栈
mcls.myvirfunc(); // 用对象来调用虚函数 就跟调用普通成员函数一样
// 不需要通过虚函数表 汇编代码就2步
// 这里就是静态联编(对象模型9 而且这里只是定义一个虚函数并不存在多态,所以在编译的时候就可以确定具体调用哪个函数
Myclass *pointcls = new Myclass(); // 堆
pointcls->myvirfunc(); //要通过虚函数指针找到虚函数表 然后通过虚函数表找到函数入口地址
// 完成对虚函数调用 汇编代码需要七步
delete pointcls;
}
/*
编译器视角可能就是
(*pointcls->vptr[0])(pointcls)
vptr 虚函数指针
0 虚函数第一项
传 pointcls 函数第一项编译器添加的this指针
(*pointcls->vptr[0]) 虚函数地址
*/
class Myclass{
public:
int i;
void myfunc(int abc){
i += abc;
}
virtual void myvirfunc(){
printf("myvirfunc()被调用 this = %p\n ", this);
//myvirfunc2(); // 走虚函数表 偏移四个字节
Myclass::myvirfunc2(); // 直接调用虚函数 效率更好 这种写法压制了虚拟机制
// 这种用类名::虚函数名() 明确调用虚函数的方式等价于直接调用一个普通函数
}
virtual void myvirfunc2(){
printf("myvirfunc()被调用 this = %p\n ", this);
}
}
int main(){
Myclass mcls; // 栈
mcls.myvirfunc();
}
-----------------------------------------------------------------
class Myclass{
public:
int i;
void myfunc(int abc){
i += abc;
}
virtual void myvirfunc(){
printf("myvirfunc()被调用 this = %p\n ", this);
}
virtual void myvirfunc2(){
printf("myvirfunc()被调用 this = %p\n ", this);
}
static void staticfunc(){
printf("staticfunc()被调用 this = %p\n ", this")
}
}
int main(){
Myclass mcls;
mcls.staticfunc(); // 虽然跟着类走但是对象也可以调用
Myclass *pointcls = new Myclass();
pointcls->staticfunc();
delete pointcls;
Myclass::staticfunc();
// 以上三种写法没有任何区别
((* Myclass)0)->staticfunc();
// 因为static 没有this指针 ,所以不能操作不是static的变量
// 普通成员函数传递一个this指针 是为了操作成员变量
//((* Myclass)0)->myfunc(12);
// 能编译通过 但是 运行时报错 因为这个myfunc的this指针是0
// 如果这个函数不操作成员变量那就不会报错
// 这种语法主要是为了支持有些成员函数独立于类对象之外的存取操作
}
/*
静态成员函数没有this指针
无法操作类中普通的非静态成员变量
静态成员函数不能在函数位添加const ,不能设置位virtual
可以使用类对象调用 ,调用方式多变 ,但是转成汇编代码 都一样
静态成员函数 等同于非成员函数 有的需要提供回调函数的这种场合 可以将静态成员函数作为回调函数
*/