关于虚函数的一点有关问题

关于虚函数的一点问题虚函数的一些大致都了解了,关于父类指向子类有点疑问。class Base {public:virtual vo

关于虚函数的一点问题
虚函数的一些大致都了解了,关于父类指向子类有点疑问。
class Base {
     public:
            virtual void f() { cout << "Base::f" << endl; }
            virtual void g() { cout << "Base::g" << endl; }
            virtual void h() { cout << "Base::h" << endl; }
};

class Derive : public Base{
public:
            virtual void f() { cout << "Derive::f" << endl; }
            virtual void g1() { cout << "Derive::g1" << endl; }
};
Derive继承了Base,覆盖了函数f,那么在调用的经常会有
Base *b = new Derive();
b->f();
这里b应该是调用了Derive中的f(),输出就是Derive::f
然后如果我b->g1();就会报错
我的疑问就是在Base *b = new Derive();这里,
新建了Derive类的,用父类Base指向了它,事实准确的说应该是指向了Derive的虚函数表,因为虚函数表是在对象的最前位置(这么理解对不对?)
Derive的虚函数的排列顺序是 B:f(),B:g(),B:h(),D:g1()。
那么显然指针指向这个表时,前三个虚函数可以调用是没有问题的,最后一个D:g1()不能调用,能解释下吗?
[解决办法]
g1还是g?
我要先确定一下,你是否存在拼写错误。


如果不是拼写问题。
那么g1是只存在派生类中,并不在基类中,于是在这两个类的关系中,g1和重写没关系啊。
[解决办法]

引用:
引用:g1还是g?
我要先确定一下,你是否存在拼写错误。


如果不是拼写问题。
那么g1是只存在派生类中,并不在基类中,于是在这两个类的关系中,g1和重写没关系啊。
没有写错,g1只是在派生类中,派生类就重写了基类中的f。我的问题就是
Base *b = new Derive();这个b是指向了什么,我想知道我红色字处的……

g1是存在的,但是编译器不知道这一点。比如说你强转一下类型为子类就能用了,也不会出错,虽然日常工作不可能有这样的需求。
[解决办法]
引用:
引用:g1 都不是 Base 的成员,b->g1(); 当然会报错了,name lookup 都过不了关,根本到不了运行期呢。
虚函数的虚字也并非虚无缥缈的虚,多少得有点根基啊。如果 b->g1(); 这句能正常调用,那岂不是任何一个具有虚函数的类都能够无限的调用任何函数,因为你总可以假设被调用的函数在某一个可能还不存在的派生类中有定义。
……

标准不要求虚函数表存在,更没要求一定要在对象最前端,虽然 VS 系列编译器倾向于这么做,另外虚继承多重继承一上来,虚表在哪里都有可能。最好的理解就是 g1 非 Base 成员,调用失败,不要试图从编译器细节猜测标准。
[解决办法]
引用:
对学习编程者的忠告:
眼过千遍不如手过一遍!
书看千行不如手敲一行!
手敲千行不如单步一行!
单步源代码千行不如单步对应汇编一行!


哥们,你确定你明白虚函数?
[解决办法]
那么Base *b = new Derive();指向了哪里呢? 

就是父类的指针,指向了一个子类对象。跟虚函数表没什么直接的关系,不要被自以为是误导。

就LZ列出的类,虽然我没有深入研究过虚函数表,但是我详细,逻辑上有两张虚函数表:
第一个是所有基于Base的虚函数表,有f,g,h三个函数;
第二个是所有基于Drived的虚函数表,有g1函数。

父类的指针,指向了一个子类对象,这时只能查到f,g,h的虚函数表。