The polymorphism and virtual function of C + +

Source: Internet
Author: User

Polymorphism and virtual function of http://www.cnblogs.com/CaiNiaoZJ/archive/2011/08/11/2134673.htmlC++

The polymorphism in object-oriented programming is to send the same message to different objects, and different objects produce different behaviors for the same message. In the program, the message is called the function, the different behavior refers to the different implementation method, namely executes the different function body. It can also be said that the implementation of "one interface, a variety of methods."

From the perspective of implementation, polymorphism can be divided into two categories: compile-time polymorphism and run-time polymorphism. The former is implemented by static linking, such as overloading of functions in C + + and overloading of operators. The latter is realized by dynamic linking, the polymorphism in C + + is mainly realized by virtual function, and it is the main content that we should talk about today.

1. But before I say virtual functions, I'd like to start by describing a copy-compatible relationship between a base class and a derived class object. It is also the basis for learning virtual functions afterwards. We sometimes assign integer data to variables of the double type. Before assigning a value, convert the shaping data to a double-precision variable that assigns it to a double-precision type. This automatic conversion and assignment between different types of data is called assignment compatibility. Similarly, there is an assignment compatibility relationship between the base class and the derived class, which means that any place where the base class object is needed can be replaced with a public derived class object. Why only public inheritance is possible, because derived classes in public inheritance retain all members in the base class except for construction and destruction, the access rights of the base class's public or protected members are preserved as is, and the public functions of the base class can be called outside the derived class to access the private members of the base class. Therefore, the functions that the base class can implement can also be derived classes.

So how exactly do they manifest? (1) A derived class object is assigned a value directly to the base class, the assignment effect, the value of the data member in the base class data member and the derived class is the same, (2) The derived class object can initialize the base class object reference, (3) The address of the derived class object can be assigned to the pointer of the base class object, and (4) The function parameter is a reference to the base class object When calling a function, you can use the object of the derived class as an argument;

#include <iostream>
#include <string>

Class Abcbase
{
Private
Std::string ABC;
Public
Abcbase (std::string ABC)
{
ABC=ABC;
}
void Showabc ();
};

void Abcbase::showabc ()
{
std::cout<< "Letter Abc=>" <<ABC<<std::endl;
}

Class X:public Abcbase
{
Public
X (std::string x): Abcbase (x) {}
};

void function (Abcbase &base)
{
BASE.SHOWABC ();
}


int main ()
{
Abcbase Base ("A");
BASE.SHOWABC ();

x x ("B");
Base=x;
BASE.SHOWABC ();

Abcbase &base1=x;
BASE1.SHOWABC ();

Abcbase *base2=&x;
BASE2->SHOWABC ();

function (x);

return 0;
}

Results:

Note that: First, the derived class must be public-inherited when it is assigned to a base class and derived class object. Second, only the derived class object is allowed to assign a value to the base class object, which in turn is not allowed;

2. The virtual function, which allows the connection between the function call and the function body to be established at run time, determines how the action is determined at run time. The format of the virtual function declaration:

Virtual return type function name (formal parameter list)

{

function body

}

So what's the use of defining virtual functions? Let's take a look at the following example:

#include <iostream>
#include <string>


Class Graph
{
Protected
Double X;
Double y;
Public
Graph (double x,double y);
void Showarea ();
};

Graph::graph (double x,double y)
{
this->x=x;
this->y=y;
}

void Graph::showarea ()
{
std::cout<< "Calculating the plot area" <<std::endl;
}

Class Rectangle:public Graph
{
Public
Rectangle (double x,double y): Graph (x, y) {};
void Showarea ();
};

void Rectangle::showarea ()
{
std::cout<< "Rectangular area:" <<x*y<<std::endl;
}

Class Triangle:public Graph
{
Public
Triangle (Double d,double h): Graph (d,h) {};
void Showarea ();
};

void Triangle::showarea ()
{
std::cout<< "Triangle area:" <<x*y*0.5<<std::endl;
}

Class Circle:public Graph
{
Public
Circle (Double R): Graph (r,r) {};
void Showarea ();
};

void Circle::showarea ()
{
std::cout<< "Circular area:" <<3.14*x*y<<std::endl;
}

int main ()
{
Graph *graph;

Rectangle Rectangle (10,5);
graph=&rectangle;
Graph->showarea ();

Triangle Triangle (5,2.4);
graph=&triangle;
Graph->showarea ();

Circle Circle (2);
graph=&circle;
Graph->showarea ();

return 0;
}

Results:

The result seems to be different from what we imagined, since the graph Class (graph Class) object graph pointer points to the rectangle class (Rectangle Class) object, the Triangle Class (triangle Class) object, and the Circle Class (Circle Class) object, Then you should execute their own corresponding member function Showarea (), how can the result be the graph Class (graph Class) object graph in the member function? This seems to differ from the members of the derived class that we talked about in the inheritance and derivation (2) section of C + +, which overrides the members of the base class that use the same name (the derived class object calls the member function from its own class, not the base class), but when the base class object pointer points to the object of the public derived class, It can access only the members inherited from the base class, not the members defined in the derived class. However, a dynamic pointer is used to express the nature of a dynamic invocation, which is the object that the current pointer points to, and the member function of that object's corresponding class is called. That is how to solve the problem, then the virtual function reflects its role. In fact, we only need to add a keyword to the Showarea () function declaration that appears in all the classes in the previous sample code, virtual:

#include <iostream>
#include <string>


Class Graph
{
Protected
Double X;
Double y;
Public
Graph (double x,double y);
Voidvirtual Showarea ();//defined as virtual function or virtual void Showarea ()
};

Graph::graph (double x,double y)
{
this->x=x;
this->y=y;
}

void Graph::showarea ()
{
std::cout<< "Calculating the plot area" <<std::endl;
}

Class Rectangle:public Graph
{
Public
Rectangle (double x,double y): Graph (x, y) {};
Virtualvoid Showarea ();//defined as virtual function
};

void Rectangle::showarea ()
{
std::cout<< "Rectangular area:" <<x*y<<std::endl;
}

Class Triangle:public Graph
{
Public
Triangle (Double d,double h): Graph (d,h) {};
Virtualvoid Showarea ();//defined as virtual function
};

void Triangle::showarea ()
{
std::cout<< "Triangle area:" <<x*y*0.5<<std::endl;
}

Class Circle:public Graph
{
Public
Circle (Double R): Graph (r,r) {};
Virtualvoid Showarea ();//defined as virtual function
};

void Circle::showarea ()
{
std::cout<< "Circular area:" <<3.14*x*y<<std::endl;
}

int main ()
{
Graph *graph;

Rectangle Rectangle (10,5);
graph=&rectangle;
Graph->showarea ();

Triangle Triangle (5,2.4);
graph=&triangle;
Graph->showarea ();

Circle Circle (2);
graph=&circle;
Graph->showarea ();

return 0;
}

The rest of the code is intact, so the result of running it is what we need:

After a member function in a base class is declared as a virtual function, the section in the later derived class is redefined. When defined, however, its function prototypes, including the return type, function name, number of arguments, and order of parameter types, must be identical to the prototype in the base class. In fact, in the above-mentioned modified example code, as long as the virtual function is explicitly declared in the base class, it is necessary to explicitly declare it in the subsequent derived class, which can be omitted, because the system will determine whether it is not a virtual function according to its exact same prototype as the virtual function in the base class. Therefore, virtual functions in the derived class above are not explicitly declared or virtual. Finally, the virtual function is supplemented by a few points: (1) because the virtual function is based on assignment compatibility, and the condition that the assignment is compatible is that the derived class derives from the base class public. Therefore, using virtual functions, derived classes must be the base class public derivation, (2) the definition of virtual functions, not necessarily in the highest class, but in the hierarchy of the need for dynamic polymorphism in the highest class of the declaration of virtual function, (3) although in the above example code main () main function implementation part, We can also access virtual functions using the corresponding graphical objects and point operators, such as Rectangcle.showarea (), but this call is statically linked at compile time, and it does not take full advantage of the properties of virtual functions. Only through the base class object to access the virtual function to obtain the characteristics of the dynamic Union; (4) A virtual function is still a virtual function regardless of how many times it is inherited by the public, and (5) The virtual function must be a member function of the class, not a friend function, or a static member function. Because a virtual function call relies on a particular object class to determine which function to activate, (6) An inline function cannot be a virtual function, because an inline function cannot dynamically determine its position in the run, even if the virtual function is defined inside the class, and is considered non-inline at compile time; (7) The constructor cannot be a virtual function;

If you create a derived class nameless object in main () main function and define a pointer to a base class object, and assign the address of a nameless object to a base class object pointer, when we use the delete operator to undo a nameless object, the system executes only the base class destructor, not the derived class destructor. Like what:

#include <iostream>
#include <string>


Class Graph
{
Protected
Double X;
Double y;
Public
Graph (double x,double y);
Voidvirtual Showarea ();//defined as virtual function or virtual void Showarea ()
~graph ();
};

Graph::graph (double x,double y)
{
this->x=x;
this->y=y;
}

void Graph::showarea ()
{
std::cout<< "Calculating the plot area" <<std::endl;
}

Graph::~graph ()
{
std::cout<< "Call Graph class destructor" <<std::endl;
}

Class Rectangle:public Graph
{
Public
Rectangle (double x,double y): Graph (x, y) {};
Virtualvoid Showarea ();//defined as virtual function
~rectangle ();
};

void Rectangle::showarea ()
{
std::cout<< "Rectangular area:" <<x*y<<std::endl;
}

Rectangle::~rectangle ()
{
std::cout<< "Call Rectangle class destructor" <<std::endl;
}

int main ()
{
Graph *graph;
Graph=new Rectangle (10,5);
Graph->showarea ();

Delete graph;

return 0;
}

Results:

Because when you revoke a derived class object that the pointer graph refers to, when you call the destructor, a static union is used, and only the destructor of the graph class is called. If you also want to invoke the destructor of the derived class rectangle class, you can define the destructor of the graph class as a virtual destructor. The general format for which it is defined:

Virtual ~ Class name ()

{

function body

};

Although the destructor of a derived class differs from the destructor name of the base class, if the destructor of the base class is defined as a virtual function, the destructor for all derived classes derived from that base class is automatically created as a virtual function. We add the keyword virtual to the graph class's destructor in the previous example, and then the result is executed:

Obviously the result is what we need.

3. After using the virtual function in the above example, it is found that the function body of the virtual function in the graph Class (graph Class) is not used at all, even if it is used, the base class embodies the abstract concept of the graph and is not associated with the concrete thing. Therefore, the virtual function in the base class has no substantive function. So we only need to leave a function name in the base class, and the implementation is left to the derived class to define. In C + +, the pure virtual function is used to illustrate. The general form of pure virtual functions:

Virtual return type function name (formal parameter list) = 0;

The "= 0" Here is not the return value of the function is equal to zero, it just plays a formal role, tell the compiler system "This is pure virtual function." Pure virtual functions do not have function functions and cannot be called.

Class Graph
{
Protected
Double X;
Double y;
Public
Graph (double x,double y);
Voidvirtual Showarea () =0;//define pure virtual functions
};

Graph::graph (double x,double y)
{
this->x=x;
this->y=y;
}

4. If there is at least one pure virtual function in a class, then the class is called an abstract class. So the graph class above is abstract class. There are several points to note for abstract classes: (1) Abstract classes can only be used as base classes for other classes, cannot create abstract class objects, (2) do not allow abstract classes to be derived from concrete classes (ordinary classes that do not contain pure virtual functions);(3) Abstract classes cannot be used as parameter types, return types, and display conversion types for functions; If the implementation of a pure virtual function is not defined in a derived class, it is inherited only as a pure virtual function of the base class. Then the derived class is still an abstract class. Once the implementation of the virtual function in the base class is given, the derived class is not an abstract class, but a concrete class of object can be established.

5. In the end, I will use an example to summarize what we are saying today (development tools: VS2010):

#include <iostream>
#include <string>


Class Graph//Abstract classes
{
Protected
Double X;
Double y;
Public
Graph (double x,double y);
void virtual Showarea ();//defined as virtual function or virtual void Showarea ()
Voidvirtual Showarea () =0;//define pure virtual functions
Virtual~graph ();//define Virtual destructor
};

Graph::graph (double x,double y)
{
this->x=x;
this->y=y;
}

void Graph::showarea ()
{
std::cout<< "Calculating the plot area" <<std::endl;
}

Graph::~graph ()
{
std::cout<< "Call Graph class destructor" <<std::endl;
}

Class Rectangle:public Graph
{
Public
Rectangle (double x,double y): Graph (x, y) {};
void Showarea ();//virtual function
~rectangle ();//Virtual destructor
};

void Rectangle::showarea ()
{
std::cout<< "Rectangular area:" <<x*y<<std::endl;
}

Rectangle::~rectangle ()
{
std::cout<< "Call Rectangle class destructor" <<std::endl;
}

Class Triangle:public Graph
{
Public
Triangle (Double d,double h): Graph (d,h) {};
Virtualvoid Showarea ();//virtual function
~triangle ();//Virtual destructor
};

void Triangle::showarea ()
{
std::cout<< "Triangle area:" <<x*y*0.5<<std::endl;
}

Triangle::~triangle ()
{
std::cout<< "Call Triangle class destructor" <<std::endl;
}


Class Circle:public Graph
{
Public
Circle (Double R): Graph (r,r) {};
Virtualvoid Showarea ();//virtual function
~circle ();//Virtual destructor
};

void Circle::showarea ()
{
std::cout<< "Circular area:" <<3.14*x*y<<std::endl;
}

Circle::~circle ()
{
std::cout<< "Call circular class destructor" <<std::endl;
}

int main ()
{
{
Graph g (10,10);//abstract class cannot establish object

Graph *graph;

Rectangle Rectangle (10,5);
graph=&rectangle;
Graph->showarea ();

Triangle Triangle (5,2.4);
graph=&triangle;
Graph->showarea ();


Graph *GRAPH1;
Graph1=new Circle (2);//new operator establishes nameless object
Graph1->showarea ();

Delete Graph1;//delete operator revokes a derived class Circle nameless object
}

return 0;
}

Results:

The polymorphism and virtual function of C + +

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.