Virtual & Abstract (C++)

  C++通過虛函數實現多態。"無論發送消息的對象屬於什麼類,它們均發送具有同一形式的消息,對消息的處理方式可能隨接收消息的對象而變"的處理方式被稱爲多態性。而虛函數是通過virtual關鍵字來限定的。

Virtual 函數(virtual function)

 Virtual 是C++ OO(面向對象機制) 機制中很重要的關鍵字。虛函數就是因爲成員函數加了關鍵字virtual, 可見它的重要性。

                                            

  簡單模型:

   在類Base中加入了virtual關鍵字的函數就是虛擬函數(例如函數print),於是在Base的派生類Derived中就可以通過重寫虛擬函數來實現對基類虛擬函數的覆蓋。當基類Base的指針point指向派生類Derived的對象時,對point的print函數的調用實際上是調用Derived的print函數而不是Base的print函數。這就是面向對象中多態性體現。

NOTE:函數的重載和此機制是完全不同的

   (1)重載的幾個函數必須在同一個類中;virtual 函數 相應覆蓋的函數必須在有繼承關係的不同的類中。

   (2)virtual 函數 相應 覆蓋的幾個函數必須函數名、參數、返回值都相同

       重載的函數必須函數名相同,參數不同。參數不同的目的就是爲了在函數調用的時候編譯器能夠通過參數來判斷程序是在調用的哪個函數。這也就很自然地解釋了爲什麼函數不能通過返回值不同來重載,因爲程序在調用函數時很有可能不關心返回值,編譯器就無法從代碼中看出程序在調用的是哪個函數了。

    (3) virtual 函數 相應的被覆蓋函數前必須加關鍵字virtual

         重載和virtual沒有任何瓜葛,加不加都不影響重載的動作。

     虛擬函數,只有通過基類指針或引用間接指向派生類子類型纔會起作用。


 In object-oriented programming, a virtual function or virtual method is a function or method whose behavior can be overridden within an inheriting class by a function with the same signature. This concept is an important part of the ploymorphism portion of object-oriented programming (OOP).


值得關注的幾點:

  (1) 定義一個函數爲虛函數,不代表函數爲不被實現的函數。

  (2) 定義它爲虛函數是爲了允許用基類的指針來調用子類的這個函數。

  (3) 定義一個函數爲純虛函數,才代表函數沒有被實現。


Purpose

  The concept of the virtual function solves the following problem:

  In object-oriented programming when a derived class inherits form a base class, an object of the derived class may be referred to via a pointer or reference of either the base class type or the derived class type. If there are base class methods overridden by the derived class, the method actually called by such a reference or pointer can be bound either 'early' (by the compiler), according to the declared type of the pointer or reference, or 'late' (i.e. by the runtime system of the language), according to the actual type of the object referred to.

  Virtual function are resolved 'late'. If the function in question is 'virtual' in the base class, the most-derived class's implementation of the function is called according to the actual type of the object referred to, regardless of the declared type of the pointer or reference. If it is not 'virtual', the method is resolved 'early' and the function called is selected according to the declared type of the pointer or reference.

  Virtual function allow a program to call methods that don't necessarily even exist at the moment the code is compiled.

  In C++, virtual methods are declared by prepending the virtual keyword to the function's declaration in the base class. This modifier is inherited by all implementations of that method in derived classes, meaning that they can continue to over-ride each other and be late-bound.


Virtual Destructors 

  Object-oriented languages typically manage memory allocation and deallocation automatically when objects are created and destroyed. However, some object-oriented languages allow a custom destructor method to be implemented, if desired. If the language in question uses automatic memory management, the custom destructor (generally called a finalizer in this context) that is called is certain to be the appropriate one for the object in question. For example, if an object of type Wolf that inherits Animal is created, and both have custom destructors, the one called will be the declared in Wolf.

  In manual memory management contexts, the situation can be more complex, particularly as relates to static dispatch. If an object of type Wolf is created but pointed to by an Animal pointer, and it is this Animal pointer type that is deleted, the destructor called may actually be the one defined for Animal and not the one for Wolf, unless the destructor is virtual. This is particularly the case with C++, where the behavior is a common source of programming errors.


Behavior During Construction and Destruction

  Languages differ in their behavior while the constructor or destructor of an object is running. For some languages, notably C++, the virtual dispatching mechanism has different semantics during construction and destruction of an object. While it is recommended that virtual function calls in constructors should avoided for C++, in some other languages, for example C# and Java, the derived implementation can be called during construction and design patterns such as the Abstract Factory Pattern actively promote this usage in languages supporting the ability.


純虛函數:

  C++ 語言爲我們提供了一種語法結構,通過它可以指明,一個虛擬函數只是提供了一個可被子類型改寫的接口。但是,它本身並不能通過虛擬機制被調用。這就是純虛擬函數(Pure Virtual Function)。純虛擬函數的生命如下所示:

                                                            

   這裏函數聲明後面緊跟賦值0。定義純虛函數是爲了實現一個藉口,起到一個規範的作用,規範繼承這個類的程序員必須實現這個函數。


   引入純虛函數的原因:

    1.爲了方便使用多態特性,我們常常需要在基類中定義虛擬函數。

    2.在很多情況下,基類本身生成對象時不合情理的。例如,動物作爲一個基類可以派生出老虎、貓等子類,動物對象明顯不合常理。

     NOTE:

    爲了解決上述問題,引入純虛函數的概念,將函數定義爲純虛函數(方法: virtual returnType Function() = 0;),則編譯器要求在派生類中必須予以重寫以實現多態性。同時含有純虛函數的類稱爲抽象類,它不能生成對象。聲明瞭純虛函數的類是一個抽象類。用戶不能創建類的實例,只能創建它的派生類的實例。

    純虛函數最顯著的特徵是: 它們必須在繼承類中重新聲明函數(不要後面=0,否則該派生類也不能實例化),而且它們在抽象類中往往沒有定義。

    定義純函數的目的在於,使派生類僅僅只是繼承函數的接口。


抽象類

  抽象類是一種特殊的類,它是爲了抽象和設計的目的爲建立的,它出於繼承層次結構的較上層。

   (1) 抽象類的定義:稱帶有純虛函數的類爲抽象類。

   (2) 抽象類的作用:

         是將有關的操作作爲結構接口組織在一個繼承層次結構中,由它來爲派生類提供一個公共的根,派生類將具體實現在其基類中作爲接口的操作。所以,派生類實際上刻畫了一組子類的操作接口的通用語義,這些語義也傳給子類,子類可以具體實現這些語義,也可以再將這些語義傳給自己的子類。

    (3) 使用抽象類時,注意:

        抽象類只能作爲基類來使用,其純虛函數的實現由派生類給出。

        抽象類不能定義對象。


Abstract classes and pure virtual functions

  A pure virtual function or pure virtual method is a virtual function that is required to be implemented by a derived class, if that class is not abstract. Classes containing pure vitual methods are termed "abstract" and they cannot be instantiated directly. A subclass of an abstract class can oly be instantiated directly if all inherited pure virtual methods have been implemented by that class or a parent class. Pure virtual methods typically have a declaration (signature) and no definition (implementation).

  Although pure virtual methods typically have no implementation in the class that declares them, pure virtual methods in C++ are permitted to contain an implementation in their declaring class, providing fallback or default behavior that a derived class can delegate to , if appropriate.

  Pure virtual functions can also be used where the method declarations are being used to define an interface - similar to what the interface keyword in Java explicitly specifies. In such a use, derived classes will supply all implementations. In such a design pattern, the abstract class which serves as an interface will contain only pure virtual functions, but no data members or ordinary methods. In C++, using such purely abstract classes as interfaces works because C++ supports multiple inheritance. However, because may OOP languages do not support multiple inheritance, they often provide a separate interface mechanism. An example is the Java programming language.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章