2010-05-05 83 views
4

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

我看到BASE然后派生每次调用。我正在为面试做一些评估,我想确保我有这个直接。的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个BASE
方法1 DERVIED

+0

“如果两种方法都被声明为虚拟的,” - 派生类中的覆盖是虚拟的(尽管人们只是为了清晰起见而将它添加),所以这与问题无关。 – UncleBens 2010-05-05 21:11:26

+1

你正在寻找的演员将是'((BaseClass&)myClass)。Method1();',或者多一点C++:'static_cast (myClass).Method1();' – GManNickG 2010-05-05 21:14:24

+0

另外,你应该避免使用C风格的类型转换。 – rlbond 2010-05-05 21:14:26

回答

6

你在这里看到的是"slicing"。将派生类的对象投射到基类中“切掉”不在基类中的所有内容。

在C++虚函数中,只能对指针或引用正确工作。对于示例工作的权利,你必须做到以下几点:

 

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

或者你可以做

 

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

Dima:+1不要忘记提及'在C++虚函数中只能正确工作指针或引用' – 2012-01-23 09:55:32

12

否,因为如果一个功能通过指针或参考称为虚拟函数机制只。否则,使用该对象的静态类型来确定要调用哪个函数。

+1

啊。谢谢大家的解释! :D – bobber205 2010-05-05 21:19:59

5

由于投((BaseClass)myClass)切片myClass对象从DerClassBaseClass,所以只有BaseClass的实施Method1()被调用。

对于多态性正常工作,您必须通过指针调用的方法:

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() 
14

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

myClass.Method1()是一个直接调用。由于myClass是一个对象,而不是一个参考,所以没有虚拟调度(不需要)。

+0

切片上的良好通话。要求考生明确区分C++还是说Java或C#,这总是一个很好的问题。 – 2010-05-06 00:57:11

0

((BaseClass的)MyClass的).Method1(); - >对象切片因此总是调用基类方法。 真正的多态行为是通过可以包含派生类的任何对象的基类指针实现的。 因此,要实现你想要的东西,你需要做派生类对象的地址,并将它转换为基类指针。如下所示: ((BaseClass *)& myClass) - > Method1();