基类中非虚成员函数调用被子类重写的成员函数的有关问题
基类中非虚成员函数调用被子类重写的成员函数的问题。
#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。
#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。