C++调用类成员函数的过程
我知道C++有一个虚函数列表,对象有指向虚函数列表的指针,对于有虚函数的类对象调用虚函数时通过虚函数列表里面的指针实现的。。但是对于普通的非虚函数是怎么实现调用的呢、?是...
我知道C++有一个虚函数列表,对象有指向虚函数列表的指针,对于有虚函数的类对象调用虚函数时通过虚函数列表里面的指针实现的。。但是对于普通的非虚函数是怎么实现调用的呢、? 是怎么找到非虚函数的入口地址? 好像类对象里面只有类的一些数据成员。。求解惑 求详细的内存层次的变化
展开
2个回答
展开全部
程序运行时内存中有一个区域【代码区】,所有代码段都存放在这里,包括虚函数和非虚函数
普通函数调用时,直接转换成代码去区的地址,生成文件时就定了
类的虚表可以看成是类的静态数据成员,类的每个对象有个指针指向这个虚表,即为虚表指针
当虚函数调用时,就是从虚表指针找到虚表,进而找到了虚函数的地址
普通函数调用时,直接转换成代码去区的地址,生成文件时就定了
类的虚表可以看成是类的静态数据成员,类的每个对象有个指针指向这个虚表,即为虚表指针
当虚函数调用时,就是从虚表指针找到虚表,进而找到了虚函数的地址
更多追问追答
追问
比如:class A{ public:void f(){} };
A a;
a.f(); //调用f();
我知道编译时类中函数会在代码区生成,还有一个偏移量来定位什么的(这不是很懂), 但是a.f是怎么知道代码区f()函数的绝对地址的? 就是想知道运行a.f()时,内存里面发生了什么变化。
追答
class A
{
public:
void f() {}
virtual void g() {}
};
class B : public A
{
public:
void h() {}
virtual void g() {}
};
void Test(A& a)
{
a.f();
a.g();
}
以上是代码
下面是Test两个函数调用的汇编代码
a.f();
001F6FCE mov ecx,dword ptr [a]
001F6FD1 call A::f (01F1433h)
a.g();
001F6FD6 mov eax,dword ptr [a]
001F6FD9 mov edx,dword ptr [eax]
001F6FDB mov esi,esp
001F6FDD mov ecx,dword ptr [a]
001F6FE0 mov eax,dword ptr [edx]
001F6FE2 call eax
001F6FE4 cmp esi,esp
001F6FE6 call __RTC_CheckEsp (01F12E9h)
由此可见,f函数直接寻址(在编译时就已经确定地址了01F1433h),而g函数通过虚指针寻址
展开全部
在static成员函数中传递类本身的指针,就可以在内部调用这个指针的具体动作(做一下强制转换)。
由于static成员函数本身的作用域是属于类的public/protected的,所以它既能被外部调用,也能直接使用类内部的/public/protected/private成员。
这解决了不能通过C的函数指针直接调用C++的类普通public成员函数的问题。
struct test
{
char (*cptr_func)(void *);
};
class C
{
public:
static char cpp_func(void *vptr){
//针对这个对象调用他的成员函数
return static_cast<C*>(vptr)->_xxx();
}
char _xxx(){
std::cout<<"hei! _xxx called"<<std::endl;
return 'a';
}
};
int main()
{
struct test c_obj;
class C cpp_obj;
c_obj.cptr_func = C::cpp_func;
std::cout<< c_obj.cptr_func(&cpp_obj) <<std::endl;
return 0;
}
#include <iostream>
struct test
{
char (*cptr_func)(void *);
};
char cpp_friend_func(void*);
class C
{
friend char cpp_friend_func(void *vptr);
public:
char _xxx(){
std::cout<<"hei! _xxx called"<<std::endl;
return 'a';
}
};
char cpp_friend_func(void *com_on) //friend function have the ability of calling class public/private/protected member functions
{
return static_cast<C*>(vptr)->_xxx();
}
int main()
{
struct test c_obj;
class C cpp_obj;
c_obj.cptr_func = cpp_friend_func;
std::cout<< c_obj.cptr_func(&cpp_obj) <<std::endl;
return 0;
}
由于static成员函数本身的作用域是属于类的public/protected的,所以它既能被外部调用,也能直接使用类内部的/public/protected/private成员。
这解决了不能通过C的函数指针直接调用C++的类普通public成员函数的问题。
struct test
{
char (*cptr_func)(void *);
};
class C
{
public:
static char cpp_func(void *vptr){
//针对这个对象调用他的成员函数
return static_cast<C*>(vptr)->_xxx();
}
char _xxx(){
std::cout<<"hei! _xxx called"<<std::endl;
return 'a';
}
};
int main()
{
struct test c_obj;
class C cpp_obj;
c_obj.cptr_func = C::cpp_func;
std::cout<< c_obj.cptr_func(&cpp_obj) <<std::endl;
return 0;
}
#include <iostream>
struct test
{
char (*cptr_func)(void *);
};
char cpp_friend_func(void*);
class C
{
friend char cpp_friend_func(void *vptr);
public:
char _xxx(){
std::cout<<"hei! _xxx called"<<std::endl;
return 'a';
}
};
char cpp_friend_func(void *com_on) //friend function have the ability of calling class public/private/protected member functions
{
return static_cast<C*>(vptr)->_xxx();
}
int main()
{
struct test c_obj;
class C cpp_obj;
c_obj.cptr_func = cpp_friend_func;
std::cout<< c_obj.cptr_func(&cpp_obj) <<std::endl;
return 0;
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询