Virtual function

Virtual function

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

Purpose

The concept of the virtual function solves the following problem:

In OOP when a derived class inherits from a base class, an object of the derived class may be referred to (or cast) as either being the base class type or the derived class type. If there are base class functions overridden by the derived class, a problem then arises when a derived object has been cast as the base class type. When a derived object is referred to as being of the base's type, the desired function call behavior is ambiguous.

The distinction between virtual and not virtual resolves this ambiguity. If the function in question is designated "virtual" in the base class then the derived class's function would be called (if it exists). If it is not virtual, the base class's function would be called.

Virtual functions overcome the problems with the type-field solution by allowing the programmer to declare functions in a base class that can be redefined in each derived class.

Example

For example, a base class Animal could have a virtual function eat. Subclass Fish would implement eat() differently than subclass Wolf, but you can invoke eat() on any class instance referred to as Animal, and get the eat() behavior of the specific subclass.

This allows a programmer to process a list of objects of class Animal, telling each in turn to eat (by calling eat()), with no knowledge of what kind of animal may be in the list. You also do not need to have knowledge of how each animal eats, or what the complete set of possible animal types might be.

The following is an example in C++:
#include using namespace std; class Animal{public: virtual void eat() { cout << "I eat like a generic Animal." << endl; ; class Wolf : public Animal{public: void eat() { cout << "I eat like a wolf!" << endl; ; class Fish : public Animal{public: void eat() { cout << "I eat like a fish!" << endl; ;

class GoldFish : public Fish{public: void eat() { cout << "I eat like a goldfish!" << endl; ;

class OtherAnimal : public Animal{}; int main(){ Animal* anAnimal [5] ; anAnimal [0] = new Animal(); anAnimal [1] = new Wolf(); anAnimal [2] = new Fish(); anAnimal [3] = new GoldFish(); anAnimal [4] = new OtherAnimal(); for (int i = 0; i < 5; i++) { anAnimal [i] ->eat(); delete anAnimal [i] ; } return 0;}

Output with the virtual method Animal::eat(): I eat like a generic Animal. I eat like a wolf! I eat like a fish! I eat like a goldfish! I eat like a generic Animal.

Output if Animal::eat() were not declared as virtual: I eat like a generic Animal. I eat like a generic Animal. I eat like a generic Animal. I eat like a generic Animal. I eat like a generic Animal.

Java

In Java, all methods are by default "virtual functions". The following is an example in Java:public class Animal { public void eat() { System.out.println("I eat like a generic Animal."); } public static void main(String [] args) { Animal [] anAnimal = new Animal [4] ;

anAnimal [0] = new Animal(); anAnimal [1] = new Wolf(); anAnimal [2] = new Fish(); anAnimal [3] = new OtherAnimal();

for (int i = 0; i < 4; i++) { anAnimal [i] .eat(); } public class Wolf extends Animal { public void eat() { System.out.println("I eat like a wolf!"); public class Fish extends Animal { public void eat() { System.out.println("I eat like a fish!"); public class OtherAnimal extends Animal {}

Output: I eat like a generic Animal. I eat like a wolf! I eat like a fish! I eat like a generic Animal.

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 that is not abstract. Classes containing pure virtual methods are termed "abstract;" they cannot be instantiated directly, and a subclass of an abstract class can only 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).

As an example, an abstract base class "MathSymbol" may provide a pure virtual function doOperation(), and derived classes "Plus" and "Minus" implement doOperation() to provide concrete implementations. Implementing doOperation() would not make sense in the "MathSymbol" class as "MathSymbol" is an abstract concept whose behaviour is defined solely for each given kind (subclass) of "MathSymbol". Similarly, a given subclass of "MathSymbol" would not be complete without an implementation ofdoOperation().

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 behaviour that a derived class can delegate to if appropriate.

Pure virtual functions are also used where the method declarations are being used to define an interface for which derived classes will supply all implementations. An abstract class serving as an interface contains only pure virtual functions, and no data members or ordinary methods. Use of purely abstract classes as interfaces works in C++ as it supports multiple inheritance. Because many OO languages do not support multiple inheritance they often provide a separate interface mechanism. This is seen in Java for example.

C++

In C++, pure virtual functions are declared using a special syntax [ "= 0" ] as demonstrated below. class Abstract {public: virtual void pure_virtual() = 0; };The pure virtual function declaration provides only the prototype of the method. Although an implementation of the pure virtual function is typically not provided in an abstract class, it may be included. Every non-abstract child class is still required to override the method, but the implementation provided by the abstract class may be called in this way:

void Abstract::pure_virtual() { // do something } class Child : Abstract { virtual void pure_virtual(); // no longer abstract, this class may be // instantiated. }; void Child::pure_virtual() { Abstract::pure_virtual(); // the implementation in the abstract class // is executed }

Java

In Java, pure virtual methods are declared using the "abstract" keyword. Such a method cannot have a body. A class containing abstract methods (either directly, or inherited and not overridden) must itself be declared abstract. (But the converse is not true - an abstract class is not required to have any abstract methods.) An abstract class cannot be instantiated.abstract class B { abstract void a_pure_virtual_function();}

Java also uses interfaces. All of the methods declared in an interface are implicitly abstract:interface C { void a_pure_virtual_function();}

Behavior During Construction

Languages differ in their behaviour while the constructor of an object is running. For some languages, notably C++, the virtual dispatching mechanism is not used during construction as the invariants of derived classes are not yet set up and calling a method on such an object is risky. While it is recommended that virtual function calls in constructors should be avoided for C++ [cite web |title=Never Call Virtual Functions during Construction or Destruction |last=Meyers|first=Scott|date=June 6, 2005 |url=http://www.artima.com/cppsource/nevercall.html] , in some other languages, for example Java and C#, 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++

#include #include

using namespace std;

class Base { public: Base() { cout << "Constructing " << length() << endl; }

virtual int length() const { return 0; } };

class Derived : public Base { string m_name;

public: Derived(const string& name) : m_name(name.empty() ? "" : name) // Member variable m_name is never empty {}

virtual int length() const { return m_name.size(); } };

int main() { Derived("hi"); // Expected output: "Constructing 2"

return 0; }Output: Constructing 0

Java

public class Base { public int length() { return 0; } public Base() { System.out.println("Constructing " + length()); } static class Derived extends Base { String name_; public Derived(String name) { name_ = name != null ? name : ""; // Class invariant name_ is not null } public int length() { return name_.length(); } // Assume name_ is not null }

public static void main(String [] args) { new Derived("Ooops"); // NullPointerException, Derived.name_ has not been assigned to yet This is because the constructor of Base is executed before the constructor of Derived. As the constructor of Base calls length(), a null pointer exception is thrown.

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. One such language is C++, and as illustrated in the following example, it is important for a C++ base class to have a virtual destructor to ensure that the destructor from the most derived class will always be called. In the example below having no virtual destructor, while deleting an instance of class B will correctly call destructors for both B and A if the object is deleted as an instance of B, an instance of B deleted via a pointer to its base class A will fail to call the destructor for B.

#include using namespace std;

class A { public: A() { } ~A() { cout << "Destroy A" << endl; } }; class B : public A { public: B() { } ~B() { cout << "Destroy B" << endl; } }; int main() { A* b1 = new B; B* b2 = new B; delete b1; // According to the C++ standard, // the behaviour of this is undefined. // Usually, only ~A() is called though b1 is an instance // of class B because ~A() is not declared virtual. delete b2; // Calls destructors ~B() and ~A() return 0; }

Output: Destroy A Destroy B Destroy A

Correctly declaring the destructor for class A as virtual ~A() will ensure that the destructor for class B is called in both cases with the example above.

ee also

*Inheritance (computer science)
*Superclass (computer science)
*Virtual inheritance

References


* [http://www.parashift.com/c++-faq-lite/virtual-functions.html C++ FAQ Lite] Copyright © 1991-2006, Marshall Cline.


Wikimedia Foundation. 2010.

Игры ⚽ Нужно сделать НИР?

Look at other dictionaries:

  • Virtual function table — Таблица виртуальных методов (англ. virtual method table, VMT) координирующая таблица или vtable механизм, используемый в языках программирования для поддержки динамического соответствия (или метода позднего связывания). Допустим, программа… …   Википедия

  • Virtual method table — A virtual method table, virtual function table, dispatch table, or vtable, is a mechanism used in programming language to support dynamic dispatch (or run time method binding).Suppose a program contains several classes in an inheritance hierarchy …   Wikipedia

  • Virtual inheritance — For inheritance of virtual functions, see virtual function. In the C++ programming language, virtual inheritance is a kind of inheritance that solves some of the problems caused by multiple inheritance (particularly the diamond problem ) by… …   Wikipedia

  • Virtual Orchestra — is a term used to identify a variety of different types of technology and art forms. Most commonly used to refer to orchestral simulation, either for pre recorded or live environments, it also has been used to describe other activities, such as… …   Wikipedia

  • Virtual instrumentation — is the use of customizable software and modular measurement hardware to create user defined measurement systems, called virtual instruments. Traditional hardware instrumentation systems are made up of pre defined hardware components, such as… …   Wikipedia

  • Virtual II — Virtual ] [ (pronounced virtual two ), is a software application that emulates the Apple II series of computers on an Apple Macintosh computer running Mac OS X. The emulator supports these 8 bit Apple II machines: * [Apple II series#Apple… …   Wikipedia

  • Virtual water — (also known as embedded water, embodied water, or hidden water) refers, in the context of trade, to the water used in the production of a good or service. For instance, it takes 1,300 cubic meters of water on average to produce one metric tonne… …   Wikipedia

  • Virtual synchrony — is an interprocess messaging passing (sometimes called event queue management) technology. Virtual synchrony systems allow programs running in a network to organize themselves into process groups , and to send messages to groups (as opposed to… …   Wikipedia

  • Virtual work — on a system is the work resulting from either virtual forces acting through a real displacement or real forces acting through a virtual displacement. In this discussion, the term displacement may refer to a translation or a rotation, and the term …   Wikipedia

  • Virtual management — seeks to separate certain responsibilities of managers from the actual site of production, the workers and resources at that site. It orients managers more directly to the needs of a service economy wherein commodity and product relations are no… …   Wikipedia

Share the article and excerpts

Direct link
Do a right-click on the link above
and select “Copy Link”