C ++和Java中的虚函数

我一直在读虚拟function,发现,

VF用于inheritance类的多态性。

因此,如果类和派生类都具有相同的函数名,则VF会将相应的函数绑定到函数调用。

即如果所讨论的函数在基类中被指定为虚拟,则将调用派生类的函数。 如果它不是虚拟的,则将调用基类的函数。

默认情况下,在Java中:所有函数都是Virtual C ++:非虚拟,可以使用final,private访问修饰符在Java中使用Virtual,而在C ++中使用Virtual关键字将函数设置为虚拟。

基于以上理论,我写了代码:

#include  class base{ public : virtual void function1(){ std::cout<<"BaseVirtual"<<std::endl; } void function2(){ std::cout<<"Base NonVirtual"<<std::endl; } }; class derieved: public base { public : void function1(){ std::cout<<"Derieved Virtual"<<std::endl; } void function2(){ std::cout<<"Derieved NonVirtual"<<std::endl; } }; int main() { base b1; derieved d1; b1.function1(); b1.function2(); d1.function1(); d1.function2(); } 

现在基于这样的事实,如果它是一个虚函数,那么只调用派生类函数,我上面程序的输出应该是:

 BaseVirtual Base NonVirtual Derieved Virtual Base NonVirtual 

然而,它出来了:

 BaseVirtual Base NonVirtual Derieved Virtual Derieved NonVirtual 

当然一定是对的。 所以我的问题是输出完全违反了语句如果有问题的函数在基类中被指定为virtual,那么将调用派生类的函数。 如果它不是虚拟的,则将调用基类的函数。 电话:

  d1.function2(); 

是..当且仅当您尝试使用基类指针访问派生类对象时,虚拟的角色才会出现。

以你为例: –

 #include  class base{ public : virtual void function1(){ std::cout<<"BaseVirtual"<function1(); b1->function2(); return 0; } 

输出: –

 Derieved Virtual Base NonVirtual 

现在,您正在创建一个basederived对象,然后直接在这些对象上调用function1function2 。 在这些条件下, virtual (或缺乏)根本没有任何区别。

至少在C ++中,对于virtual意味着任何东西,您需要使用指向基类的指针(或引用),该基类引用可能是基类或派生类的对象:

 base *b2 = &d1; // invoke non-virtual function. Inovkes base::function1, because we're using // pointer to base. b2->function1(); // invoke virtual function. Invokes derived::function2 because the pointee object // is a derived. b2->function2(); 

如果你有(例如)一个指向对象的指针集合,那么这一点特别有用,那些指针引用的对象可能是几种不同类型中的任何一种。 其中一个经典的例子是基础shape类,其中包含linecirclesquare等。 当您调用每个的draw成员时,每个draw成员都会绘制自己的形状。 在这种特殊情况下,您的基类可能是一个抽象基类 – draw成员被声明为“纯虚拟”,这意味着您无法创建基本shape类的对象,并创建派生类的实例,必须覆盖draw成员函数:

 class shape { public: virtual void draw() = 0; }; class circle : public shape { public: virtual void draw() { /* draw itself */ } }; 

然后,在你的绘图程序中,你有一个(指向)用户创建的形状的集合,并将它们全部绘制出来,你只需要遍历集合并告诉每个人绘制自己。 更高级别的代码不需要知道或关心特定形状是圆形,正方形,三角形等。

 for (int i=0; idraw(); 

C ++中的多态性需要利用指针。 如果您将示例更改为:

 base *b1 = new base(); base *d1 = new derived(); 

这实际上将利用虚拟机制。 但是,您似乎与多态性背后的基本思想相混淆。 如果将类定义为派生类,当然它将调用derived类中定义的函数,同样也调用base

编辑:为了使这更明确,这是输出和解释:

 b1->function1(); //Will call base::function1() b1->function2(); //Will call base::function2() d1->function1(); //Will call derived::function1() d2->function2(); //Will call derived::function2() 

所有多态/虚拟调用都允许您将派生指针视为基类型,同时在其上调用(正确的)派生函数。 所以,如果你有另一个function,如:

 void foo(base& b) { b.function1(); } 

然后传递b1将调用base::function1() ,传递d1将调用derived::function1()