虚函数在继承中表现得很奇怪?

时间:2011-07-01 11:23:55

标签: c++ inheritance

Lemme通过举例解释我的问题:

#include <iostream>

class PC
{
public:
    PC():Data(0)
    {
    }
    virtual void display()
    {
        std::cout<<"The data is :"<<Data<<std::endl;
    }
protected:
    int Data;
};

class SmartPC:private PC
{
public:
    SmartPC():PC()
    {
    }
    void convert()
    {
        PC* temp=static_cast<PC*>(this);
        temp->display();
    }
    void display()
    {
        std::cout<<"The data is (in bb):"<<a<<std::endl;
    }
};

int main()
{
    SmartPC SmrtPC;
    PC* miniPC= static_cast<PC*>(&SmrtPC);
    SmrtPC.convert();
}

根据Scott Meyers的说法:static_cast<PC*>(this);将创建SmartPC的临时基本副本。但是temp->display();执行了派生类的display()函数。为什么会这样?它不应该执行base display()的功能,因为该对象现在完全是SmartPC基础的副本吗?

另一个问题是,如果我在temp->data;函数中添加行convert(),它会说 PC::Data受到保护,但我是从派生类范围访问它,即SmartPC,为什么它不起作用?

感谢任何帮助。

2 个答案:

答案 0 :(得分:5)

  

根据scott meyers的说法:static_cast<PC*>(this);将创建SmartPC的临时基本副本。但temp->display();执行派生类的display()函数为什么会这样?它应该执行base display()的功能,因为该对象现在完全是SmartPC基础的副本。

没有创建副本,您只是将一个指针

由于类是多态的,通过指针调用virtual函数会导致调用函数的“正确”版本(根据对象的动态类型,这是SmartPC *)。

相反,如果display不是virtual,则会调用基类的版本,因为对于非virtual方法,它是静态类型用于确定要调用哪个版本的指针。

display virtual也在SmartPC,即使未明确指定,在覆盖继承的virtual函数时隐含virtual限定符


请注意,如果您这样做:

PC temp(*this);

您实际上已经创建了当前对象的副本,“切片”为PC类型的对象。这称为“对象切片”,由PC的复制构造函数执行;通常这是不受欢迎的行为(因为派生类的对象实际上成为基类的对象,并且多态性不像某些人所期望的那样工作)。


  

另一个问题是,如果我在temp->data;函数中添加行convert(),它会说PC::Data受到保护,但我从派生类范围即SmartPC访问它,为什么它不起作用?

从概念上讲,当您尝试访问temp->data时,您尝试访问其他对象的private成员(temp实际上this并不重要),所以访问被拒绝。您访问protected成员的“派生类权限”仅适用于this

答案 1 :(得分:1)

它不是类的副本,它是对基类对象的引用,因此,它的行为与其他任何类似。

您无法访问受保护成员的原因是您使用了私有继承。