A detailed explanation of C + + programming polymorphism Concept _c language

Source: Internet
Author: User
Tags gety inheritance numeric value prepare multiple inheritance in c

Polymorphism (polymorphism) is an important feature of object-oriented programming. If a language only supports classes and does not support polymorphism, it cannot be called an object-oriented language, it can only be said to be object-based, such as Ada, VB belongs to this class. C + + supports polymorphism, and can achieve polymorphism in C + + programming. Using polymorphism, you can design and implement an easily scalable system.

As the name implies, polymorphism means that a thing has many forms. Polymorphism of the English word polymorphism from the Greek root poly (meaning "many") and morph (meaning "form"). In C + + programming, polymorphism refers to functions with different functions can use the same function name, so you can use a function name to invoke different content functions. Polymorphism is generally expressed in object-oriented methods: sending the same message to different objects, and different objects producing different behaviors (i.e. methods) when they are received. In other words, each object can respond to common messages in its own way. The so-called message, is called the function, different behavior refers to different implementations, that is, the implementation of different functions.

In fact, we have been exposed to excessive polymorphism many times, such as overloading of functions, operator overloading are polymorphic phenomena. Only then did not use the jargon of polymorphism. For example, using the operator "+" to add two numeric values is to send a message that calls the operator + function. In fact, integral type, single precision, double precision addition operation process is different, is realized by the function of various content. Obviously, they respond to the same message in a different way or behavior.

Many examples of polymorphism can be seen in real life. such as school principals to the community to release a message: September 1 The new school year. Different objects respond differently: Students have to prepare their textbooks to attend school on time, parents to raise tuition fees, teachers to prepare classes, and logistics departments to prepare classrooms, dormitories and canteens ... Since the tasks of the various persons have been stipulated in advance, it is polymorphism that all people know what they should do when they get the same message. It can be assumed that if the use of polymorphism, then the principal to the students, parents, teachers, logistics departments, and many other different objects issued a notice, respectively, specify how each person should be notified after the notice should be done. Obviously this is a very complex and meticulous work. One man does everything, and the toil is not pleasing. Now, using the polymorphism mechanism, the principal in the release of the message, do not have to one by one specific considerations of how different types of personnel are executed. As to what the various personnel should do after receiving the news, it is not a temporary decision, but the working mechanism of the school is decided in advance. The headmaster needs to keep releasing all kinds of news, and the staff will work methodically according to the predetermined plan.

Similarly, in C + + programming, the method of responding to messages is defined in different classes, and when these classes are used, it is not necessary to consider what type they are, as long as the message is published. Just as when you use operator "", you don't have to consider whether the added value is integral, single, or double, and you use "+" directly, regardless of which numeric value is added. It can be said that this is a status quo method, regardless of the variety of objects, users are using the same form of information to invoke them, so that they respond to the prior arrangements.

From the point of view of system realization, polymorphism is divided into two kinds: static polymorphism and dynamic polymorphism. In the past, the polymorphism of function overload and operator overload is static polymorphism, and the system can decide which function to call when the program compiles, so static polymorphism is called the polymorphism of compile time. Static polymorphism is implemented through the overload of a function (operator overloading is also a function overload). Dynamic polymorphism is the object that the operation is dynamically determined during the process of running the program. It is also called Run-time polymorphism. Dynamic polymorphism is realized through virtual function (virtual fiinction).

Here is an example of a connecting link. On the one hand, it is an example of an integrated application of inheritance and operator overload content, which can be used to further integrate what has been learned earlier, and, on the other, as a basic use case for discussing polymorphism.

I hope you will patiently and thoroughly read and digest the program to find out every detail of it.

[Example] Create a point class first, containing the data member x,y (coordinate point). Take it as the base class, derive a circle (circle) class, increase the data member R (RADIUS), and then take the Circle class as the direct base class, derive a cylinder (cylinder) class, and then increase the data member H (high). Requires writing programs that overload the operator "<<" and ">>" so that it can be used to output the above class object.

This example is not very difficult, but the program is very long. For a larger program, it should be divided into several steps. Declare the base class first, then declare the derived class, step through, and debug in steps.

1) Declaring base class point

A class can write out a section that declares the base class point as follows:

#include <iostream>
//Declaration class point class point
{public: Point
 (float x=0,float y=0); Constructor
 void SetPoint (float, float) with default parameters//Set coordinate value
 float GetX () const {return x}//read x coordinate
 float GetY () const {RET Urn y;} Read Y coordinates
 friend Ostream & operator << (ostream &,const Point &);//overloaded operator "<<"
protected:/ /protected member
 float x, y;
};
The following defines the member function of the point class point
::P oint (float a,float b)//point constructor
{//X,y initialization
 x=a;
 y=b;
}
void Point::setpoint (float a,float b)//set the coordinate value of x and y
{//To assign new value to X,y
 x=a;
 y=b;
}
Overloaded operator "<<" enables it to output the coordinates of the
ostream & operator << (ostream &output, const point &p)
{
 output<< "[" <<p.x<< "," <<p.y<< "]" <<endl;
 return output;
}

The above completes the declaration of the base class point class.

In order to improve the efficiency of the program debugging, advocating the program step-by-step debugging, do not write a long program after the unified debugging, so that in the compilation may occur at the same time a large number of compile errors, in the face of a long program, program personnel often difficult to quickly and accurately find the wrong location. To be good at a large program into a number of files, compiled separately, or step-by-step debugging, first through the most basic part, and then gradually expand.

Now you want to debug the base class declaration written above, check it for errors, and write the main function. It's actually a test program.

int main ()
{point
 P (3.5,6.4);//Create Point class object P
 cout<< "x=" <<p.getx () << ", y=" << P.gety () <<endl; Output P's coordinate value
 p.setpoint (8.5,6.8);//reset P's coordinate value
 cout<< "P (new):" <<p<<endl; Output P-point coordinates with overloaded operator "<<" return
 0;
}

The GETX and Gety functions are declared as constant member functions that allow functions to refer only to the data in the class, but not to modify them to ensure the security of the data in the class. Data members X and Y are declared as protected, so that they can be accessed by derived classes (if declared private, derived classes are inaccessible).

The program compiles and runs with the following results:

x=3.5,y=6.4
P (new): [8.5,6.8]

The test program examines the functions of the functions in the base class, as well as the role of operator overloading, proving that the program is correct.

2) declaring a derived class circle

On top of that, write out the part that declares the derived class circle:

Class Circle:public Point//circle is a common derived class of the point class
{public
:
Circle (float x=0,float y=0,float r=0);//constructor
void Setradius (float);//Set radius value
float Getradius () const; Read radius value
float area () const; to compute a circle space
friend Ost Ream &operator << (ostream &,const Circle &); Overloaded operator "<<"
private:
float radius;
};
Defines the constructor, initializes the center coordinates and radii
circle::circle (float a,float b,float R):P oint (a,b), radius (r) {}
//Set radius value
void Circle::setradius (float R) {radius=r}
Read radius value
float Circle::getradius () const {return radius;}
Calculate the Circle area
float Circle::area () const
{return
 3.14159*radius*radius;
}
Overloaded operator "<<" to make it output the information of the circle as specified
ostream &operator << (ostream &output,const Circle &c)
{
 output<< "center=[" <<c.x<< "," <<c.y<< "],r=" <<c.radius<< ", area=" <<c.area () <<endl;
 return output;
}

To test the definition of the above circle class, you can write the following main function:

int main ()
{
Circle C (3.5,6.4,5.2);//Set Circle class object C, and given the center coordinates and radius
cout<< "original circle:\\nx=" < <c.getx () << ", y=" <<c.gety () << ", r=" <<c.getradius () << "area=" <<c.area () <<endl; Output center coordinates, radius and area
C.setradius (7.5);//Set RADIUS value
c.setpoint (5,5);//set Center coordinate value x,y
cout<< "New circle:\\n" <<c; Output the information of a circular object with the overloaded operator "<<" point
&pRef=c;//pref is the reference variable of the point class, initialized by C
cout<< "pref:" <<pRef; Output pref information return
0;
}

The program compiles and runs with the following results:

Original circle: (output original circle data)
x=3.5, y=6.4, r=5.2, area=84.9486
New circle: (Output modified round data)
center=[5,5], R =7.5, area=176.714
pref:[5,5] (data of the "point" of the center of the output circle)

As you can see, an operator "<<" overload function is declared in the point class, and an operator "<<" is declared once in the Circle class, and the two overloaded operator "<<" content is different. Compiling the system at compile time determines which operator overloaded function is invoked based on the type of output item. Line 7th of the main function outputs C with "cout<<", calling the operator overloading function declared in the Circle class.

Note Line 8th of the main function:

 Point & pref = C;

Defines the reference variable pref of the point class and initializes it with a derived class Circle object C. As we've already mentioned earlier, derived class objects can override the base class object for reference initialization or assignment of the base class object (see: C + + base class and derived class conversions). Now circle is a common derived class for point, so pref cannot be considered a C alias, and it gets the starting address for C, which is just an alias to the base class part of C that shares the same segment of storage unit as the base class section in C. So when you use "cout<<pref" output, the operator overload function declared in the circle is invoked instead of the operator overloading function declared in the point, which outputs the "dot" information rather than the "round" information.

3 declare circle derived class cylinder

The Circle class has been derived from the base class point earlier, and the cylinder class is now derived from circle.

Class Cylinder:public circle//Cylinder is the Circle common derived class {Public:cylinder (float x=0,float y=0,float r=0,float);//Construction Letter Number of void setheight (float); Set the cylinder high float getheight () const; Read the column High Loat area () const; Calculate circular surface area Float volume () const; Compute cylinder Volume friend ostream& operator << (Ostream&,const cylinder&);
Overloaded operator << protected:float height;//column High}; Define constructor Cylinder::cylinder (float a,float b,float r,float h): Circle (a,b,r), height (h) {}//Set column high void Cylinder:: SetHeight (float h) {height=h}//Read cylinder high float cylinder::getheight () const {return height;}//Compute round surface area float Cylinder::area () const {return 2*circle::area () +2*3.14159*radius*height}//Calculate cylinder Volume float Cylinder::volume () const {return Circle::area (
) *height;} Ostream &operator << (ostream &output,const cylinder& cy) {output<< "center=[" <<cy.x< < "," <<cy.y<< "],r=" <<cy.radius<< ", h=" <<cy.height << "\\narea=" << Cy.area () << ", volume=" <<cY.volume () <<endl;
return output;
 }//overloaded operator "<<"

You can write the following main function:

int main ()
{
 Cylinder cy1 (3.5,6.4,5.2,10);//Define Cylinder Class object Cy1
 cout<< "\\noriginal cylinder:\\nx=" <<cy1.getx () << ", y=" <<cy1.gety () << ", r="
  <<cy1.getradius () << "h=" < <cy1.getheight () << "\\narea=" <<cy1.area ()
  << "Volume=" <<cy1.volume () <<endl Cy1 data Cy1.setheight (15) with the system-defined operator "<<",
 set the cylinder height
 Cy1.setradius (7.5),//Set the circle radius
 cy1.setpoint ( 5,5)//Set the center coordinate value x,y
 cout<< "\\nnew cylinder:\\n" <<cy1;//with overloaded operator "<<" output cy1 data point
 & Pref=cy1;//pref is the reference variable of the Point class object
 cout<< "\\npRef as a": "<<pref;//pref as a" dot "Output
 Circle & Cref=cy1;//cref is the reference variable of the Circle class object
 cout<< "\\ncRef as a Circle:" <<cref;//cref as a "circle" output return
 0;
}

The results of the operation are as follows:

Original cylinder: (output cy1 initial value)
x=3.5, y=6.4, r=5.2, h=10 (center coordinates x,y. Radius r, High h)
area=496.623, volume=849.486 (cylindrical surface area and volume volume)
New cylinder: (output cy1 new value)
center=[5,5], r=7.5, H=15 (output center coordinates in [5,5] form)
area=1060.29, volume=2650.72 (cylindrical area and volume volume)
pref as a point:[5,5] (pref as a "point" output)
CRef as a circle:center=[5,5], r=7.5, area=176.714 (CRef as a "circle" output)

Note: The area function is defined in the cylinder class, which has the same name as the area function in the Circle class, based on the principle covered by the same name as we explained earlier (see: Two semantic questions for multiple inheritance in C + +), Cy1.area () It calls the area function of the cylinder class (for cylindrical surface area), rather than the square function of the circle class. Note that these two area functions are not overloaded functions, they are not only the same function names, but function types and parameters are the same, two functions with the same name are not in the same class, but are in the base class and derived classes, which are overridden by the same name. Overloaded functions must have at least one different arguments and parameter types, or the system cannot determine which function to call.

The main function, line 9th, uses "Cout<<cy1" to output Cy1, at which point the overloaded operator "<<" declared in the cylinder class is invoked, outputting the relevant data of the cylinder cy1 in the manner specified in the overload.

The last 4 lines in the main function have the same meaning as when you define the Circle class. Pref is the reference variable of the point class, initialized with Cy1, but it is not cy1 alias, but the alias of the base point in Cy1, which is output as a point class object when outputting pref, that is, it is a "dot". Similarly, CREF is a reference variable of the circle class, initialized with Cy1, but it is only the alias of the direct base class circle part of the cy1, which is output as a CRef class object when outputting circle, it is a "circle" rather than a "cylinder". From the results of the output, you can see which operator function is invoked.

There is static polymorphism in this example, which is caused by operator overloading (note that the 3 operator functions are overloaded rather than overridden with the same name because there is a different type of parameter). As you can see, when compiling a system at compile time, you can determine which overloaded operator function should be called.

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.