Virtual functions and polymorphic overviews

Source: Internet
Author: User

First, the article for the reason

Bill again wrote the article for the reason ~ ~ Long to understand this problem, this is the C + + field is more difficult to fix a piece of knowledge, and recently in the design mode, there is involved in this piece, the previous learned not easy to play to forget, so simply study a little, or encounter, use when not flustered ~ So I have this article.

Second, from compile time and run time to say 2.1 compile time:

As the name implies is the time to compile. Is that the compiler helps you translate the source code into code that the machine can recognize. (It is, of course, only in the general sense that it may actually be a language translated into an intermediate state.) For example, Java has only the bytecode recognized by the JVM, and only MSIL that is recognized by the CLR in C #)

At compile time, it is simple to do some translation work. If you find an error The compiler will tell you. For example, click on Microsoft's vs point under build, if there is errors or warning information, it is the compiler check out. The so-called error is a compile-time error, the process of doing type checking is called compile-time type checking, or static type check (so-called static does not put the code to run in memory, but only the code as text to scan). Therefore, it is certainly wrong to allocate memory at compile time.

2.2 Run Time:

The so-called runtime is that the code runs and is loaded into memory. (Your code is saved on disk before it is loaded into memory and is dead, static, and only runs into memory to become alive). The Run-time type check is not the same as the previous compile-time type check (or static type check). Not a simple scan code. Instead, do some work in memory and make some judgments.

For example, in C + +:

int arr[] = {1,2,3};int result = arr[4];cout<<result<<endl;

The above code error is obvious-the array is out of bounds. But compiled with the compiler, will not error. Visible compiler is actually quite stupid, and then start debugging, may error (or may not error, I use the vs2012 debug mode is not). But the fact that the runtime does an array of bounds checking is not a feature supported in C + +, where you dubug is a check that some of the tools in VS are doing for you. If you choose release instead of debug at the point of runtime, you will find that everything is working, but the results are uncertain (because you don't know what arr[4] means in memory).

2.3 C + + polymorphism at compile time and runtime "underlying mechanism, very important":

Why isn't C + + doing array cross-check at run time?
This should be mainly due to the performance problem, C + + design in order to achieve the same efficiency as C, try not to do more at runtime to do extra checks, because this will undoubtedly degrade performance, but in some places it is necessary to do run-time type check, such as polymorphic, do not do type checking at runtime can not determine the type.

To give a simple example, if there is a parent class father, inherits from the subclass son of Father, these two classes have the virtual function fun

Father fa;Son so;fa = so;fa.Fun(); //在编译时,实际上是把Fun当作Father类中的Fun看待

But at run time actually the fun here is called the son of the function fun, so do not do run-time type checking is not OK

2.4 Compile-time polymorphic and run-time polymorphism

There is also a problem with polymorphism at compile time and runtime, which is important- compile-time polymorphic and run-time polymorphism

Polymorphism is one of the important features of object-oriented programming. Polymorphism refers to the different actions that occur when different objects receive the same message. The polymorphism of C + + is embodied in the two aspects of running and compiling, and the polymorphism of the program runtime is embodied by inheriting virtual function, while the polymorphism of the program compile is embodied in the overloading of functions and operators.

C + + supports two types of polymorphism:

compile-time polymorphism: events that occur before a program runs--function overloading, operator overloading--static binding
run-time polymorphism: events that occur during program run--virtual function mechanism--dynamic binding

Three, polymorphism of the small overview

That's the first thing that's been said.

3.1 polymorphic Definitions

Definition: Polymorphism can be simply summed up as " one interface, multiple methods ", the program at runtime to determine the function of the call, it is the core concept of object-oriented programming domain. Polymorphic (polymorphism), literally meaning multiple shapes.

C + + polymorphism is implemented through virtual functions, which allow subclasses to redefine member functions, while subclasses redefine the parent class as overwrite (override), or override.

Here I would like to add that there are two kinds of rewrite can be, directly rewrite the member function and rewrite virtual function , only rewrite the virtual function can be counted as the embodiment of C + + polymorphism.

Overloading, however, allows multiple functions with the same name, with different parameter lists, different parameter types, or different parameters. The compiler modifies the name of a function of the same name, based on a different list of these functions, producing preprocessing functions of different names to overload the problem when a function call of the same name is implemented.

3.2 Overloading and rewriting

The above definition, with a qualitative understanding, C + + polymorphism is implemented by overriding the virtual function, it is necessary to look at overloading and rewriting.
In fact, these two concepts are certainly not unfamiliar to us, but there are many details of the place is easy to ignore.

Method overloads:

  1. For object-oriented purposes, it must be in the same class
  2. Method name is the same
  3. parameter types are different such as: public void test (int i, int j) {} and public void test (int i, float j) {}
  4. The number of arguments is different, such as: public void Test (int i) {} and public void test (int i, int j) {}
  5. Independent of the return value of the method, such as: public int test (int i) {} and public void test (int i, int j) {} also belong to method overloads

Method overrides refer to methods that override the parent class

1. The class must inherit the parent class to override the parent class's methods;
2. It must be the same as the return value of the parent class's method , the parameter list and the method name are overridden! (This is important)

3.3 Early binding and late binding

The real difference between polymorphic and non-polymorphic is whether the function address is early binding or late binding . If a function is called, the call address of the function can be determined during compiler compilation, and the production code is static, and the address is early bound. If the address of a function call cannot be determined during the compiler, it needs to be determined at run time, which is late binding.

So what is the role of polymorphism, encapsulation can make code modular, inheritance can extend existing code, their purpose is to code reuse. The purpose of polymorphism is to reuse the interface . In other words, regardless of what is passed to the object of that class, functions can be called through the same interface to adapt to the implementation of the respective object.

The most common usage is to declare a pointer to a base class, use it to point to any subclass object, invoke the corresponding virtual function, and implement a different method depending on the sub-class to which it is directed. If you do not use a virtual function, that is, you are not using C + + polymorphism, when you invoke the corresponding function using the base class pointer, it will always be limited to the base class function itself, and cannot be called to a function that has been overridden in a subclass. Because there is no polymorphism, the address of the function call will be certain, and the fixed address will always be called to the same function, which will not implement an interface, the purpose of a variety of methods.

3.4 Code Analysis 3.4.1 cases 1
#include <iostream>using namespace STD;classa{ Public:voidFoo () {printf("Class A: 1\n"); }Virtual voidFun () {printf("Class A: 2\n"); }};classB: Publica{ Public:voidFoo () {printf("Class B: 3\n"); }voidFun () {printf("Class B: 4\n"); }};intMainvoid) {a A;    b b; A *p = &a;//base class pointerP->foo (); P->fun ();cout<<endl;    p = &b;    P->foo (); P->fun ();cout<<endl;    b *ptr = (b *) &a;    Ptr->foo (); Ptr->fun ();return 0;}

Run out of results

Analysis:

The first P->foo () and P->fun () are easy to understand.
 

The second output is 1, 4. P->foo () and P->fun () are the base class pointers to sub-class objects , fully embodying the polymorphic usage, P->foo () because the pointer is a base-class pointer, pointing is a fixed offset function, so this point is only the base class Foo () The code of the function, so the result of the output is still 1.

While the P->fun () pointer is a base-class pointer, the fun to point is a virtual function, because each virtual function has a list of virtual functions , when p call fun () is not directly called the function, but through the virtual function list to find the address of the corresponding function , Therefore, depending on the object pointed to, the function address will be different, here will find the corresponding subclass of the fun () function address, so the output will be the result of the subclass 4.

And there's a very sick stuff.

B *ptr = (B *)&a;ptr->foo();ptr->fun();

A pointer to a subclass that points to a base class object that is cast to the subclass address. As a result, the output of these two invocations is 3, 2.
  

   并不是很理解这种用法,从原理上来解释,由于B是子类指针,虽然被赋予了基类对象地址,但是ptr->foo()在调用的时候,由于地址偏移量固定,偏移量是子类对象的偏移量,于是即使在指向了一个基类对象的情况下,还是调用到了子类的函数,虽然可能从始到终都没有子类对象的实例化出现。

So this situation only looks at the pointer type.

The invocation of Ptr->fun () may also be due to C + + polymorphism, because it points to a base class object that, through a reference to a virtual function list, finds the address of the fun () function in the base class, and therefore calls the function of the base class.

So this situation only looks at the bound object type.

This shows that the polymorphism of the powerful, can adapt to various changes, whether the pointer is a base class or sub-class, can find the correct implementation method.

3.4.2 Cases 2
//Summary: 1, there may be a polymorphic phenomenon of virtual///2, no polymorphic (no virtual) call is called by the original type#include <iostream>using namespace STD;classbase{ Public:Virtual voidF1 (floatx) {cout<<"Base::f1 (float)"<< x <<endl; }Virtual voidF2 (floatx) {cout<<"Base::f2 (float)"<< x <<endl; }voidF3 (floatx) {cout<<"base::f3 (float)"<< x <<endl; }};classDerived: Publicbase{ Public:Virtual voidF1 (floatx) {cout<<"Derived::f1 (float)"<< x <<endl;//polymorphic, rewriting}voidF2 (intx) {cout<<"DERIVED::F2 (int)"<< x <<endl;//Hide}voidF3 (floatx) {cout<<"derived::f3 (float)"<< x <<endl;//Hide}};intMainvoid) {Derived D;    Base *pbase = &d; Derived *pderi = &d;//Good:behavior depends solely on type of the objectPBASE-&GT;F1 (3.14f);//DERIVED::F1 (float) 3.14PDERI-&GT;F1 (3.14f);//DERIVED::F1 (float) 3.14    cout<<endl;//Bad:behavior depends on type of the pointerPBASE-&GT;F2 (3.14f);//Base::f2 (float) 3.14PDERI-&GT;F2 (3.14f);//DERIVED::F2 (int) 3    cout<<endl;//Bad:behavior depends on type of the pointerPBASE-&GT;F3 (3.14f);//BASE::F3 (float) 3.14PDERI-&GT;F3 (3.14f);//DERIVED::F3 (float) 3.14    return 0;}

Operation Result:

Analysis:
First correct a mistake, many people think that rewriting and overwriting are different, actually is a thing.

Looking at the first set of outputs, this is both overriding the parent method and implementing polymorphism, although the subclass is a virtual method that can continue to be rewritten by its subclasses.

Then on the back of the two groups, another confusing concept of the heavy debut ~ ~

3.5 Confusing hidden rules

It is not difficult to distinguish between overloading and overwriting, but the hidden rules of C + + increase the complexity of the problem abruptly.

"Hide" here refers to a function of a derived class that masks a base class function with the same name.

The rules are as follows:

(1) If the function of the derived class has the same name as the function of the base class, but the parameters are different. At this point, the function of the base class is hidden, regardless of the virtual keyword (Note that it is not confused with overloading). The second group is this example, if the F2 (int x) in the Derived is changed to void F2 (float x), the output is two Derived, which is how to override the parent class method and implement polymorphism.

(2) If the function of the derived class has the same name as the function of the base class , and the parameters are the same , the base class function does not have the virtual keyword. At this point, the function of the base class is hidden (be careful not to confuse the overlay).

In the above program:

(1) The function derived::f1 (float) is covered with BASE::F1 (float).
(2) the function derived::f2 (int) hides base::f2 (float) instead of overloading.
(3) The function derived::f3 (float) hides the base::f3 (float) instead of the overlay.

Four, C + + pure virtual function 4.1 definition

A pure virtual function is a virtual function declared in a base class that is not defined in the base class, but requires that any derived class define its own implementation method. The method of implementing a pure virtual function in a base class is to add "= 0" after the function prototype
such as: virtual void funtion () =0

4.2 Introduction Reason

1, in order to facilitate the use of polymorphic features, we often need to define virtual functions in the base class.

2, in many cases, the base class itself is unreasonable to generate objects.

For example, animals as a base class can be derived from tigers, peacocks and other sub-categories, but the animals themselves generated objects are obviously unreasonable. In order to solve the above problems, the concept of pure virtual function is introduced, the function is defined as pure virtual function (method: Virtual ReturnType functions () = 0;), the compiler requirements must be overridden in the derived class to achieve polymorphism. A class that contains a purely virtual function is called an abstract class, and it cannot produce an object. This is a good solution to both of these problems.

4.3 Similarity concept

1. polymorphism
A different implementation action occurs when the same object receives different messages or when different objects receive the same message. C + + supports two kinds of polymorphism: compile-time polymorphism, run-time polymorphism.
A, compile-time polymorphism: by overloading the function of the implementation
B, run-time polymorphism: through virtual function implementation.
This one's on the top, too.

2. Virtual function
A virtual function is a member function that is declared as virtual in a base class and redefined in a derived class to implement dynamic override of a member function (override)

3. Abstract class
Classes that contain pure virtual functions are called abstract classes. Because an abstract class contains a pure virtual function that is not defined, an object of an abstract class cannot be defined.

Five, C + + polymorphic applications

The application is in the project, the complex architecture involving design patterns will be used polymorphic.
See in design mode:

It is not necessary to indicate which object to use, directly using the parent class to invoke the different methods according to the object of the child class, which is a C + + polymorphic application scenario.

-end-

Reference documents

[1] http://blog.csdn.net/hackbuteer1/article/details/7475622 (thanks to the author for making me Enlightened)

Copyright NOTICE: Welcome Reprint, note The source is good! If you do not like please leave a message to explain why again step on Oh, thank you, I can also know the reason, continuous progress!!

Virtual functions and polymorphic overviews

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.