2009-11-05 144 views
9

如果我有C++:C++虚函数的实现?

class A { 
    private: virtual int myfunction(void) {return 1;} 
} 

class B: public A { 
    private: virtual int myfunction(void) {return 2;} 
} 

然后,如果我从myfunction定义class B删除virtual,这是否意味着,如果我有一个基于class Bclass C,我不能覆盖myfunction,因为它会静态编译?

另外,我很困惑,当你在公共场合切换时会发生什么,而在这里是私人的。如果我将myfunction中的class B的定义更改为公开(并且class A中的那个保持私密),这是否是我不应该这样做的严重错误?我认为虚拟功能需要保持相同的类型,这是非法的,但请让我们知道这是不对的。

谢谢!

+5

不需要为派生类方法显式编写“虚拟”关键字。你可以忽略它,但它是一个很好的风格。 – varnie 2009-11-05 11:11:49

回答

15

'虚拟'的第一个定义是重要的定义。从基础开始的这个函数是从虚拟派生出来的,这意味着对于重新实现的虚拟函数调用你不需要'虚拟'。如果基类中的函数签名不是虚拟的,而是在派生类中是虚拟的,那么基类没有多态行为。

class Base 
{ 
    public: 
    void func(void){ printf("foo\n"); } 
}; 
class Derived1 : public Base 
{ 
    public: 
    virtual void func(){ printf("bar\n"); } 
}; 
class Derived2 : public Derived1 
{ 
    public: 
    /* reimplement func(), no need for 'virtual' keyword 
     because Derived1::func is already virtual */ 
    void func(){ printf("baz\n"); } 
}; 

int main() 
{ 
    Base* b = new Derived1; 
    Derived1* d = new Derived2; 

    b->func(); //prints foo - not polymorphic 
    d->func(); //prints baz - polymorphic 
} 
+0

谢谢,这非常有帮助! – ash 2009-11-05 11:22:14

+0

不客气。我还应该补充一点,“Base * b”实际上是Derived1。使用dynamic_cast在您需要的情况下执行安全的向下转换。 – 2009-11-05 11:28:43

+0

但作者的例子涵盖了私人成员。 – bua 2009-11-05 12:49:34

1

如果您从在B类的myfunction定义virtual

编译器将增加这个要求。为多态类型填写V-Table。

!!但是!!

你将只能访问类A的公有成员(B类:公共A)

的定义:

class B: private A 
{ 

} 

将导致A类的所有(包括公共)成员,将成为B类私人用户。 简化您无法访问A公众会员。

要解决你可以声明一些朋友:

class A 
{ 
    private: 
     friend class B; 
} 

更伟大的信息HERE

+0

感谢您的快速回复! – ash 2009-11-05 11:23:30

+0

答案对我来说有点困惑。从答案中我看出,B班不能访问他从A班继承的公共成员,然后通过宣布A的B朋友来解决。我不认为这是正确的。 B可以访问A的公共和受保护成员,但B的用户不能访问A的公共成员,这不会由朋友声明来解决。我错过了什么? – stefaanv 2009-11-05 12:04:49

+0

是的,您错过了我的示例中的私有继承。 – bua 2009-11-05 12:52:21

7

一旦一个函数在基类中变为虚拟的,它将对每个其他子类都是虚拟的。

public,protected和private不影响函数的虚拟性质。

+0

谢谢!感谢您的知名度信息。 – ash 2009-11-05 11:24:10

+0

通过使您的虚拟功能受到保护或私人化,您可以向您的课程的用户提示是否需要在子类中调用它们。 http://www.gotw.ca/publications/mill18.htm – 2010-04-09 09:10:01

0

virtual的行为是它影响该方法时,你有一种类型的指向一个亚型的对象的指针被调用。例如:

B* obj = new B; 
A* base = obj; 

当你调用obj->myfunction()发生取决于A是否宣布myfunction是虚拟的。如果它不是虚拟的,推理是:我们有一个类型为A的指针,所以我们调用A中定义的函数,结果为1。然而,如果Amyfunction定义为虚拟的,则基于实际对象的类型而不是指针的类型在运行时执行查找;由于对象实际上是B,因此使用在B中定义的实现,结果为2.

更多信息可在the C++ FAQ Lite section on virtual functions中找到。