以下三个小问题,都是我认为C++初学者应该能够回答或识别清楚的。希望大家通过题目能够挖掘出更多的信息,而不仅仅局限于解决问题。最想说的一句话:能力有限,作为抛砖引玉,希望大家一起讨论,指出错误。另外,我总是遇到一个问题,觉得有必要记录一下,所以就写下来说说,所以每篇文章可能没有单一的主题。1、先看一个简单的问题。有如下继承类:classPerson{public:voidWalk()//普通人的“走路”{cout<<"Person::WalkIamanOrdinaryPeople."<Walk();Student*ps=&s;ps->Walk();结果是这样的:分析:Walk()是一个非虚函数,是静态绑定的,所以pp和ps的类型决定了调用的版本。在这里,我想再说明一点:理解接口继承和实现继承。声明非虚函数的目的是让派生类继承该函数的接口和强制实现。因此,永远不要重新定义继承的非虚函数。2、下面的问题本质上是静态绑定和动态绑定的问题,只是看起来没有那么明显。classShape{public:enumShapeColor{Red,Green,Blue};//形状颜色";cout<<"Mycolor="<Draw();是的,(1)不指定参数通过对象调用是错误的,(2)的结果是这样的:color=0表示红色,这个你应该知道。分析:通过对象调用是静态绑定,必须指定参数值,因为静态绑定的功能不继承基类的默认参数值。动态绑定可以从基类继承参数值。注意,我这里不强调动态绑定和静态绑定的概念,但是下面一定是静态绑定:Circlecr;Circle*ps=&cr;//这还是静态绑定,静态类型Circle*,编译不通过ps->绘制();(2)我想说的第二个问题,请解释一下下面的调用结果。Shape*ps1=newRectangle;ps1->Draw();Shape*ps2=newCircle;ps2->Draw();是这样一个令人愉快的结果:你的意思是,你已经将DrawinRectangle的默认值更改为1(绿色),为什么它不起作用?分析:Rectangle::Draw的默认参数值是GREEN,但是ps2的静态类型是Shape*,所以这次调用的默认参数值来自于Shape类。如果硬要改Rectangle::Draw的参数,可以这样调用(提供参数):Shape*ps4=newRectangle;ps4->Draw(Shape::Green);Shape*ps5=newCircle;ps5->绘制(形状::绿色);这个问题是提醒大家:虚函数是动态绑定的,默认参数值是静态绑定的。因此,不应重新定义此默认参数值。3.为什么多重继承包含多个虚表指针而不是一个?这个问题是我在看一个同学的面试经历时,面试官问的。我试着回答它。我不知道是不是说到点子上了。请补充更正。答:多重继承下,因为编译器为一个派生类实现了n-1个虚表,n代表上一层基类的个数。当然,前提是每个基类至少有一个虚函数,否则编译器不会为它加上vptr和vtbl。所以虚拟表有多少,指向它们的指针自然也就有多少,而不是一个。不知道合理不合理。可能面试官想问“为什么要多张虚拟表?一张虚拟表行不行?”这是编译器制造商做的事情,标准没有规定。C++之父做出了这样一个编译器原型。通过增加vtbl的大小,每个slot上不仅有一个指针,还有一个偏移量来调整这个指针的指向。这样做的缺点是:vtbl中所有的虚函数指针都包含这样一个偏移量,假设不需要调整this点,调用时仍然需要进行偏移加法操作,虽然此时偏移量为0。此外,vtbl中每个插槽卷的扩展。这些都是效率问题。其实经常用trunk技术来调整this的方向,必须用汇编写才能获得高效率。另外,sun编译器是把多个虚表链接成一个,每个表都包含一个指向下一个表的指针(通过偏移的方式),所以需要一个指针。理解能力有限。不知道这个跟问题是不是一回事?