特别是,无论如何都不会有某种功能指针?
我认为" 带有虚函数的类是用vtable实现的 "这句话会误导你.
该短语使得听起来像具有虚拟功能的类是" 以A方式 "实现的,而没有虚函数的类是" 以B方式 "实现的.
实际上,具有虚函数的类除了作为类实现之外,还具有vtable.另一种看待它的方法是"'vtable'实现类的'虚函数'部分".
所有类(使用虚拟或非虚拟方法)都是结构.C++中结构和类之间的唯一区别是,默认情况下,成员在结构中是公共的,在类中是私有的.因此,我将在这里使用术语class来引用结构和类.记住,它们几乎是同义词!
类(结构)只是连续内存块,其中每个成员按顺序存储.请注意,由于CPU体系结构原因,某些成员之间会存在间隙,因此块可能大于其各部分的总和.
方法或"成员函数"是一种幻觉.实际上,没有"成员函数"这样的东西.函数始终只是存储在内存中的一系列机器代码指令.要进行呼叫,处理器会跳转到该内存位置并开始执行.你可以说所有方法和函数都是"全局的",任何相反的指示都是编译器强制执行的一种错觉.
显然,一个方法就像它属于一个特定的对象,所以很明显还有更多的事情发生.为了将方法(函数)的特定调用绑定到特定对象,每个成员方法都有一个隐藏参数,该参数是指向相关对象的指针.该成员是隐藏的,你不会自己将它添加到你的C++代码中,但没有什么神奇之处 - 它是非常真实的.当你这样说:
void CMyThingy::DoSomething(int arg); { // do something }
编译器真的这样做:
void CMyThingy_DoSomething(CMyThingy* this, int arg) { /do something }
最后,当你写这个:
myObj.doSomething(aValue);
编译器说:
CMyThingy_DoSomething(&myObj, aValue);
无需任何地方的函数指针!编译器已经知道您正在调用哪个方法,因此它直接调用它.
静态方法甚至更简单.它们没有this指针,因此它们的编写与编写它们完全相同.
那是!其余的只是方便的语法糖:编译器知道方法属于哪个类,因此它确保它不允许您在不指定哪个类的情况下调用该函数.它还使用这些知识转化myItem
到this->myItem
时,它的明确这样做.
(是的,这是正确的:方法中的成员访问总是通过指针间接完成,即使你没有看到一个)
(编辑:删除最后一句并单独发布,以便单独批评)
非虚拟成员函数实际上只是一个语法糖,因为它们几乎像普通函数,但具有访问检查和隐式对象参数.
struct A { void foo (); void bar () const; };
基本相同:
struct A { }; void foo (A * this); void bar (A const * this);
需要vtable,以便为特定的对象实例调用正确的函数.例如,如果我们有:
struct A { virtual void foo (); };
'foo'的实现可能近似于:
void foo (A * this) { void (*realFoo)(A *) = lookupVtable (this->vtable, "foo"); (realFoo)(this); // Make the call to the most derived version of 'foo' }