基类中非虚成员函数调用被子类重写的成员函数的有关问题

基类中非虚成员函数调用被子类重写的成员函数的问题。
#include   "stdafx.h "

class   Base
{
public:
void   DoSomethingIfValid(void);
bool   IsValid(void)   const;
};

void   Base::DoSomethingIfValid()
{
if   (IsValid())
{
//   do   something
}
}

bool   Base::IsValid()   const
{
printf( "Base::IsValid   return   false   !\n ");
return   false;
}

class   Derived   :   public   Base
{
public:
bool   IsValid(void)   const;
};

bool   Derived::IsValid()   const
{
printf( "Derived::IsValid   return   true   !\n ");
return   true;
}

int   main()
{
Derived   d;
d.DoSomethingIfValid();
return   0;
}  

这段程序里,如果基类中的IsValid成员函数不加virtual关键字,则输出结果是:

Base::IsValid   return   false   !

如果加上virtual关键字,则输出结果是:

Derived::IsValid   return   true   !

哪位能告诉我为什么输出结果不一致,虚机制在这里又是怎样工作的?
(注意我并没有用箭号调用DoSomethingIfValid方法。)

------解决方案--------------------
加了virtual以后,虚拟的是isValid()方法。

你通过d访问了base的DoSomethingIfValid方法,DoSomethingIfValid方法去调用isValid,这里就是虚拟调用了Derived的isValid。

刚才说得过了,是和虚拟机制有关系的。
------解决方案--------------------
不论是用点号,还是用箭号调用成员函数,最终都是this指针隐式实现的
----------------------
我倒不是这个意思
比如 d.DoSomethingIfValid();编译器可能改写为DoSomethingIfValid(&d)类似的代码
而DoSomethingIfValid( )
{
if (IsValid())
{
// do something
}
}
调用的时候也可能变为
DoSomethingIfValid(const Base * this )
{
if (this-> IsValid())
{
// do something
}
}类似的代码 这样的当你this-> IsValid()编译器又内部转化为(*this -> vptr[1])(this)
这样变实现了 "虚拟 "

------解决方案--------------------
楼上各位都说的在理。
小生也来评一评
先看加上virtual关键字
鸡肋的DoSomethingIfValid 调用 isValid 是通过一个叫 this 指针实现的!故,此处可以实现多态!
不管你d 是怎么调用,只能调用 鸡肋的DoSomethingIfValid 。
说到这里,就出现lz说的那样。。。

^_^ 鸡肋,食之无味
------解决方案--------------------
如果基类中的IsValid成员函数不加virtual关键字,则输出结果是:

Base::IsValid return false !
------------------------------------------------
这是正确的。
因为你在调用d.DoSomethingIfValid()时,调用的是Base::DoSomethingIfValid函数,即控制流转移到Base::DoSomethingIfValid中执行,而在Base::DoSomethingIfValid中,有一个隐含的this指针用于访问类成员,这个this指针的类型为“Base *const”,因此在Base::DoSomethingIfValid中调用IsValid()时实际上是 "this-> IsValid() ";说到这里,问题就明了了,因为this是指向Base的指针,所以当IsValid函数是virtual时调用Derived::IsValid,而当IsValid时non virtual时调用的是Base::IsValid。