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
现在,您正在创建一个base
和derived
对象,然后直接在这些对象上调用function1
和function2
。 在这些条件下, 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
类,其中包含line
, circle
, square
等。 当您调用每个的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()
。