c++ - 将基类指针赋给派生类的问题
曾经蜡笔没有小新
曾经蜡笔没有小新 2017-06-05 11:11:46
0
3
1101

将派生类地址赋给基类指针,也就是基类指针指派生类对象,也就是我们平时说的多态

但是反过来的时候,必须经过强制类型转换才可以编译通过,

下来直接代码:

#include<iostream>

usingnamespacestd;

class Base
{
public:
virtual void print()
{
    cout<<"base"<<endl;
}
};

class Derived:public Base
{
public:
void print()
{
cout<<"derived"<<endl;
}
};
int main(void)
{

Base * pb=newB ase();//定义基类指针

Derived * pd=(Derived*)pb;//赋值给派生类指针

pd->print();//调用基类的print输出base

pd->Derived::print();//调用派生类的print输出derived

return 0;
}

我想问问用pd->print()为什么调用的是基类的print

然后为什么将基类的virtual去掉之后,调用的便是派生类的print

曾经蜡笔没有小新
曾经蜡笔没有小新

全部回复(3)
滿天的星座

调用哪个虚函数是由对象所指的虚函数表所决定的,当你 new Base()的时候pb所指向的虚函数表中的虚函数是Base的,用(Derived*)强制转化并没改变,而非虚函数主要根据指针类型,也就是说pd一开始就是Derived,所以用Derived的函数,成员函数在调用时其实是调用了this指针的。

刘奇

The virtual specifier specifies that a non-static member function is virtual and supports dynamic binding. It may only appear in the decl-specifier-seq of the initial declaration of a non-static member function (i.e., when it is declared in the class definition).

Virtual functions are member functions whose behavior can be overridden in derived classes.

使用virtual的意思就是这个函数可以被子类override,使指向子类的父类指针不跟据指针本身的类别来调用这个函数,而(通过查虚函数表V-Table)调用被子类override后的函数。
值得一提的是

Base * pb=new Base();//定义基类指针
Derived * pd=(Derived*)pb;//赋值给派生类指针

这样写是不正确,至少也是不安全的,不应该将指向父类对象的父类指针赋给子类指针。

此处的pd->print指向的是虚函数表中父类的的print,所以

pd->print();                    //调用父类的print,输出base

调用的是Base::print

接下来

pd->Derived::print();

这是强行在父类对象上调用子类的函数(或者说以父类对象为this,强行调用虚函数表中的子类print),一般不推荐这么做。

伊谢尔伦

还真是这样,刚运行了一下,确实很难理解。

我说一下我的思路,不知道对不对,大家可以参考一下:

第一种情况,写了virtual,如果成员函数加virtual,说明是动态绑定,只有在执行时候才会找到被调函数的地址。但是在哪里找呢?貌似每个对象的内存中都会存在一份虚表(也有说法是每个类有一份虚表,对象共享),因为你的Derived指针指向的是Base对象的那块内存,所以系统就去那块内存的虚表中找print函数,那块内存中虚表中的print函数的地址是Base类的print函数的地址,所以调用了基类的print函数

第二种情况:把virtual给去了,那就不涉及动态绑定,函数的地址是编译时候确定的。编译时候函数地址怎么确定呢:是通过在源程序符号表中查找所得。那么主程序中pd->print(),很明显,pd是Derived类,pd->print()相当于Derived::print,那编译器就到Derived类中找喽,所以编译时期把pd->print()中print()的地址替换成Derived::print的地址,所以就调用了子类的print函数。

不知道你明白我说啥不

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!