摘录自百度知道的回答:
从语言和概念的角度来说,子类继承父类是继承了所有protected和public非static成员(static成员是共享而不是继承),而成员包括函数和数据。所以从概念上来说,成员函数和成员变量都被继承了。 从实现上来说,实现要在外显上不违反概念,在内部可以非常随意。所有的实现子类继承父类成员函数只是子类共享了父类的函数,没有两份拷贝。编译器知道父类的某成员函数的地址,那么在子类调用父类的该方法时,编译器只要产生 call 函数地址 的代码就可以调用父类的方法,完全没有必要保留两份拷贝。 换句话来说,非虚方法的调用在编译时就已经确定了,编译器掌握一切信息。编译器选择最高效的实现(只保留一份函数拷贝)来符合C++语言概念。从逻辑上认为子类继承了父类的方法。 对虚函数,如果是在子类对象上用.操作符调用虚函数,那么编译器可以确定函数地址,此时不需要使用虚函数调用机制。只有在基类指针上用->操作符调用虚函数时,才会使用虚函数调用机制。此时编译器不知道基类指针指向具体什么类型的对象,所以它不知道到底调用哪个函数,它产生类似如下代码: call [vftable + functionoffset] 也就是通过虚函数表中对应函数偏移来调用,虚函数表的布局是编译器已知的。当具体某个对象构造时,他们初始化虚表使得其中指针都指向自己的虚函数。这样就通过这个实现来满足了C++的虚函数概念。 举个例子: class base { private: int member1; protected: int member2; public: int fun(); virtual int virtualfun(); }; class derive : public base { public: int member; public: virtual int virtualfun(); }; 在代码中使用:derive test; (以微软c/c++编译器为例)那么test在内存中可能是如下布局: 110000 vftable----------->112000 110004 base::member1 110008 base::member2 11000c derive::member ---------------------------- 112000 (vftable[0])derive::virtualfun------>410000 ---------------------------- 410000 int derive::virtualfun(){ ... } 410500 int base::virtualfun(){ ... } 411000 int base::fun(){ ... }