1

我对向上转换有疑问。考虑有两个类,Class Parent 和 Class child。孩子与父母一起继承。

问题:

如果我为父对象创建对象指针,并分配子对象引用。我遵守了。输出是“对象切片”。无法访问子类特定组件

class Parent
{
public:
    int i;

    void school()
    {
        std::cout<<"Parent Class::School()"<<std::endl;
    }
    // virtual goToPlay()
    // {
    //       std::cout<<"Parent Class::goToPlay()"<<std::endl;
    // }    

 };

class Child:public Parent
{
public:
    int j;
    void goToPlay()
    {
        std::cout<<"Child Class::goToPlay()"<<std::endl;
    }
};

int main()
{
    Parent *mParent;
    Child mChild;
    mParent = &mChild;

    mParent->school();
    mParent->goToPlay(); //Error

无法访问 goToPlay() API。如果我在父类中创建了一个 goToPlay() 的虚函数,那么它是可以访问的。有谁能说说是什么原因?

4

3 回答 3

1

您显式声明Parent * mParent,因此您的对象被视为Parent. 在许多用例中,这正是您想要的——您提供了一个适当的接口来做某事,而具体使用的实现与最终用户无关:

class employee
{
    public:
        virtual double get_salary_in_usd() const = 0;
        virtual ~employee() {}
};

class software_developer : public employee
{
    public:
        double get_salary_in_usd() const { return 100000.; /* i wish */ }
        void be_awesome() {}
        ~software_developer() {}
};

void print_salary(std::shared_ptr<employee> const & emp)
{
    std::cout << "This employee earns $" << emp->get_salary_in_usd()
              << " a month." << '\n';
}

然而,在某些情况下,您需要在运行时判断您的指针是否是基类的某个子类。这dynamic_cast是为了:

software_developer me;
employee * me_generalized = &me;

software_developer * me_again = dynamic_cast<software_developer *>(
    me_generalized);
if(me_again != nullptr)
{
    me_again->be_awesome();
}

请注意,如果无法转换指针,dynamic_cast则可以返回。nullptr另请注意,RTTI 在运行时会发生这种情况,并且会减慢您的应用程序的速度。尽可能避免使用它。

于 2013-08-06T07:51:32.353 回答
1

Since your pointer type is Parent then only the Parent's api will be accessible since that is what you tell the compiler. (i.e. this pointer points to a Parent object).

In your case a virtual method will make the correct implementation being called. (this is called late binding and it is done during run time via hidden tables in the instance to find the correct address of the method's implementation which in your case is the Child implementation since mParent points to a Child instance)

于 2013-08-06T07:25:43.047 回答
1

为了Child::goToPlay()通过指针使用ParentParent必须声明它自己的函数goToPlay(),并且这个函数必须被标记virtual。然后,您的Child课程将覆盖该功能。

然后,当您调用指针时,会神奇地调用该goToPlay()函数。ParentChild

但是,您不能只对Parent.

于 2013-08-06T09:58:10.807 回答