【问题标题】:Question on Virtual Methods关于虚拟方法的问题
【发布时间】:2011-02-16 03:12:40
【问题描述】:

如果两个方法都声明为虚拟方法,那么被调用的 Method1() 的两个实例不应该是派生类的 Method1() 吗?

我每次都看到 BASE 然后 DERIVED 被调用。我正在为面试做一些评论,我想确保我有这个直截了当。 xD

class BaseClass
{
public:
    virtual void Method1()  { cout << "Method 1 BASE" << endl; }
};

class DerClass: public BaseClass
{
public:
    virtual void Method1() { cout << "Method 1 DERVIED" << endl; }
};


DerClass myClass;
    ((BaseClass)myClass).Method1();
    myClass.Method1();

方法 1 基础
方法一推导

【问题讨论】:

  • "IF 这两个方法都被声明为虚拟的," - 在派生类中,覆盖无论如何都是虚拟的(尽管人们只是为了清楚起见更喜欢将它添加到那里),所以这与问题无关。
  • 您正在寻找的演员应该是 ((BaseClass&amp;)myClass).Method1();,或者更多的 C++:static_cast&lt;BaseClass&amp;&gt;(myClass).Method1();
  • 另外,你应该避免使用 C 风格的演员表。

标签: c++ methods virtual-functions


【解决方案1】:

不,“C 风格”演员((BaseClass)myClass) 通过切片 myClass 创建一个临时的BaseClass 对象。它的动态类型是BaseClass,它根本不是DerClass,所以被调用的Method1 是基类方法。

myClass.Method1() 是直接调用。由于myClass 是一个对象,而不是引用,因此没有虚拟调度(没有必要)。

【讨论】:

  • 很好的切片。询问候选人是否清楚区分 C++ 和 Java 或 C# 总是一个很好的问题。
【解决方案2】:

不,因为虚函数机制仅在通过指针或引用调用函数时才有效。否则使用对象的静态类型来确定调用哪个函数。

【讨论】:

  • 啊。谢谢大家的解释! :D
【解决方案3】:

您在此处看到的内容称为"slicing"。将派生类的对象转换为基类会“切掉”不在基类中的所有内容。

在 C++ 中,虚函数仅适用于指针或引用。为了使您的示例正常工作,您必须执行以下操作:

DerClass myClass; ((BaseClass *) &myClass)->Method1();

或者你可以这样做

BaseClass *pBase = new DerClass; pBase->Method1();

【讨论】:

  • Dima:+1 记得提In C++ virtual functions work correctly only for pointers or references
【解决方案4】:

因为演员((BaseClass)myClass)myClass对象从DerClass切分到BaseClass,所以只调用BaseClassMethod1()实现。

为了使多态性正常工作,您必须通过指针调用方法:

DerClass myClass; 
BaseClass* ptrToMyClass = &myClass;
ptrToMyClass->Method1(); // Calls the DerClass implementation of Method1()

或参考:

DerClass myClass; 
BaseClass& refToMyClass = myClass;
refToMyClass.Method1();  // Calls the DerClass implementation of Method1()

【讨论】:

    【解决方案5】:

    ((BaseClass)myClass).Method1(); --> 对象切片因此总是会调用基类方法。 真正的多态行为是通过基类指针实现的,基类指针可以包含派生类的任何对象。 因此,要实现您想要的,您需要传递派生类对象的地址并将其类型化为基类指针。如下: ((BaseClass *) &myClass)->Method1();

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多