2011-07-01 20 views
1

让我再给予一个例子来说明我的问题:虚拟函数在继承中表现怪异?

#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(); 
} 

据斯科特迈尔斯:static_cast<PC*>(this);将创建SmartPC的温度基本副本。但temp->display();执行派生类的display()函数。为什么?它不应该执行基地的display()的功能,因为该对象现在完全是SmartPC的基础的副本?

的另一个问题是,如果我在temp->data;功能convert()添加行,它说 PC::Data是受保护的,但我从派生类范围即SmartPC访问它,那么为什么不工作?

任何帮助表示赞赏。

+1

您可以提供一个引用Meyers说的地方吗?也许你误解了他。 –

回答

5

根据斯科特迈尔斯:static_cast<PC*>(this);将创建SmartPC的临时基本副本。但是temp->display();执行了派生类的display()函数为什么这样呢?它应该执行基地的display()的功能,因为该对象现在完全是SmartPC的基础的副本。

没有副本被创建,你只能铸造指针

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

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

displayvirtual也即使它不是明确指定SmartPC,当重写继承virtual功能virtual限定符暗示)


通知,而不是,如果你做的事:

PC temp(*this); 

您实际上会创建当前对象的副本,“切片”为对象类型为PC。这称为“对象切片”,由PC的拷贝构造函数执行;大多数情况下这是不受欢迎的行为(因为派生类的对象实际上成为基类的对象,并且多晶现象不像某些人期望的那样工作)。


的另一个问题是,如果我在convert()功能temp->data;添加一行,它说PC::Data是受保护的,但我从派生类范围即SmartPC访问它,那么为什么没有工作?

在概念上,当您尝试访问temp->data你试图访问另一个对象的private成员(这并不重要temp实际上是this),所以访问被拒绝。您的“派生类特权”访问protected成员只能在this上工作。

1

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

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

+0

你能解释一下吗?你无法访问受保护成员的原因是因为你使用了私有继承**。由于派生类可以访问其受保护的成员,无论继承是在类的范围内是私有的还是公共的。谢谢 –