C ++ Virtual

Source: Internet
Author: User

VirtualIs an important keyword in the C ++ OO object-oriented mechanism. The virtual function adds the keyword virtual to the member function to show its importance.

Anyone who has learned C ++ knows that a function with the Virtual keyword added to class Base is a Virtual function such as function print ), therefore, in the Base-Derived class Derived, You can override the virtual function to overwrite the Base-class virtual function. When the Base class Base pointer point points to the object of the Derived class Derived, the call to the print function of the point actually calls the print function of the Derived instead of the print function of the Base. This is the embodiment of polymorphism in the object-oriented model. For how the virtual mechanism is implemented, see Inside the C ++ Object Model, Addison Wesley 1996)

 
 
  1. //---------------------------------------------------------  
  2. class Base  
  3. {  
  4. public:Base(){}  
  5. public:  
  6. virtual void print(){cout<<"Base";}  
  7. };  
  8. class Derived:public Base  
  9. {  
  10. public:Derived(){}  
  11. public:  
  12. void print(){cout<<"Derived";}  
  13. };  
  14. int main()  
  15. {  
  16. Base *point=new Derived();  
  17. point->print();  
  18. }   
  19. //---------------------------------------------------------  
  20. Output:  
  21. Derived  

This may make people think of the function overload, but a slight comparison will find that the two are completely different:

1) The overloaded functions must be in the same class;

The function to be overwritten must have different classes with inheritance relationships.

2) the names, parameters, and return values of the covered functions must be the same;

The names of the overloaded functions must be the same and the parameters are different. Different parameters are used to determine which function is called by the compiler during function call. This naturally explains why the function cannot be overloaded by different return values, because the program may not care about the return value when calling the function, the compiler cannot see from the code which function the program is calling.

3) The keyword Virtual must be added before the function to be overwritten;

There is no correlation between heavy load and Virtual load, and addition does not affect the operation of heavy load.

Hide C ++ rulesReferenced in "high quality C ++/C Programming Guide" Lin Rui 2001 ):

1) if the function of the derived class has the same name as the function of the base class, but the parameter is different. At this time, no matter whether there is a virtual

Keyword. The function of the base class will be hidden. Note that the function should not be confused with the overload ).

2) If the function of the derived class has the same name and parameter as the function of the base class, but the base class function does not have the virtual
Keyword. At this time, the base class functions are hidden and do not confuse with overwrite ).

Here, Dr. Lin seems to have made a mistake. C ++ does not hide the rules. Dr. Lin's summary of the hidden rules is that he mistakenly understands C ++ polymorphism. The following is an example of the hidden rule provided by Dr. Lin:

 
 
  1. #include <iostream.h>  
  2. class Base  
  3. {  
  4. public:  
  5. virtual void f(float x){ cout << "Base::f(float) " << x << endl; }  
  6. void g(float x){ cout << "Base::g(float) " << x << endl; }  
  7. void h(float x){ cout << "Base::h(float) " << x << endl; }  
  8. };  
  9. class Derived : public Base  
  10. {  
  11. public:  
  12. virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }  
  13. void g(int x){ cout << "Derived::g(int) " << x << endl; }  
  14. void h(float x){ cout << "Derived::h(float) " << x << endl; }  
  15. };  
  16. void main(void)  
  17. {  
  18. Derived d;  
  19. Base *pb = &d;  
  20. Derived *pd = &d;  
  21. // Good : behavior depends solely on type of the object  
  22. pb->f(3.14f); // Derived::f(float) 3.14  
  23. pd->f(3.14f); // Derived::f(float) 3.14  
  24. // Bad : behavior depends on type of the pointer  
  25. pb->g(3.14f); // Base::g(float) 3.14  
  26. pd->g(3.14f); // Derived::g(int) 3 (surprise!)  
  27. // Bad : behavior depends on type of the pointer  
  28. pb->h(3.14f); // Base::h(float) 3.14 (surprise!)  
  29. pd->h(3.14f); // Derived::h(float) 3.14  

Dr. Lin believes that bp and dp point to the same address, and the running results should be the same. In fact, the running results are different, so he attributed the reason to the hidden rules of C ++, in fact, this is wrong. It is determined that bp and dp call the function running result is not the address they direct to, but their pointer type. "Polymorphism works only when the base class pointer or reference indirectly points to the child type of the derived class" (C ++ Primer 3rd Edition ). Pb is the base class pointer, and pd is the pointer of the Derived class. All function calls of pd only call their own functions, which is irrelevant to polymorphism. Therefore, all function calls of pd output Derived :: it is completely normal; if the pb function call has virtual, it calls the derived class based on polymorphism. If there is no virtual, it is a normal static function call or a base class call, therefore, if the virtual f function calls the output Derived:, the other two do not have the virtual function, the output Base: is normal, nothing surprise!

Therefore, there are no so-called hidden rules. Although the "high quality C ++/C Programming Guide" is a very good book, do not be superstitious. Remember, "polymorphism works only when the base class pointer or reference points indirectly to the child type of the derived class ".

Pure virtual functions:

The C ++ language provides us with a syntax structure through which we can specify that a virtual function only provides an interface that can be rewritten by the quilt type. However, it cannot be called through a virtual mechanism. This is the pure virtual function (pure virtual function ). The declaration of pure virtual functions is as follows:

 
 
  1. Class Query {
  2. Public:
  3. // Declare a pure virtual function
  4. Virtual ostream & print (ostream & = cout) const = 0;
  5. //...
  6. };

The function declaration follows the value 0.

Contains or inherits) one or more classes of pure virtual functions are recognized by the compiler as abstract base classes. An attempt to create an independent class Object of the abstract base class may cause compilation errors. Similarly, calling a pure virtual function through a virtual mechanism is also incorrect. for example)

 
 
  1. // Query declares pure virtual functions
  2. // Therefore, programmers cannot create independent Query objects.
  3. // OK: Query sub-object in NameQuery
  4. Query * pq = new NameQuery ("Nostromo ");
  5. // Error: the new expression assigns a Query object.
  6. Query * pq2 = new Query;

Abstract base classes can only be used as sub-objects in subsequent Derived classes.

If you only know that virtual is added before the function, you only know about virtual. Another important use of virtual is virtual public, that is, virtual inheritance. Virtual inheritance is described in detail in C ++ Primer. The following is a slightly modified explanation:

By default, inheritance in C ++ is a special case of "combination of values. When we write

 
 
  1. class Bear : public ZooAnimal { ... }; 

Each Bear class object contains all non-static data members of its ZooAnimal base class sub-objects and non-static data members declared in Bear. Similarly, when the derived class itself acts as a base class object, such:

 
 
  1. class PolarBear : public Bear { ... }; 

Then, the PolarBear class object contains all non-static data members declared in PolarBear, all non-static data members of its Bear sub-objects, and all non-static data members of ZooAnimal sub-objects. In single inheritance, this special form of value-based combination supported by inheritance provides the most effective and compact object representation. Under Multi-inheritance, when a base class appears multiple times in the derived hierarchy, the main problem is the iostream class hierarchy. Both ostream and istream classes are derived from the abstract ios base class, while the iostream class is derived from ostream and istream.

 
 
  1. class iostream :public istream, public ostream { ... }; 

By default, each iostream class object contains two ios sub-objects: an instance in the istream sub-object and an instance in the ostream sub-object. Why is this not good? In terms of efficiency, it is a waste of storage areas to store two copies of ios sub-objects, because iostream only needs one instance. In addition, the ios constructor is called twice for each sub-object. The more serious problem is the Ambiguity Caused by two instances. For example, any unlimitedly modified access to ios members will cause a compilation time error: Which instance is accessed? What if ostream and istream initialize their ios sub-objects slightly differently? How does the iostream class ensure the consistency of this pair of ios values? Under the default value-based combination mechanism, there is really no way to ensure this.

The C ++ language solution is to provide another alternative to the inheritance Mechanism of "reference combination" to inherit virtual inheritance) under virtual inheritance, only one shared base class sub-object is inherited, regardless of whether the base class is at the derived level.
The number of shared base class sub-objects is called the virtual base class.

By using the keyword virtual repair declaration of a base class, you can specify it as a virtual derivative. For example, the following statement makes ZooAnimal a virtual base class for Bear and Raccoon:

 
 
  1. // The Order of public and virtual keywords is not important
  2. Class Bear: public virtual ZooAnimal {...};
  3. Class Raccoon: virtual public ZooAnimal {...};

Virtual derivation is not an explicit feature of the base class, but its relationship with the derived class as described above. Virtual inheritance provides a "reference combination ". That is to say, access to sub-objects and their non-static members is indirect. This makes it possible to combine multiple virtual base class sub-objects into a shared instance in the derived class in the case of multi-inheritance, thus providing the necessary flexibility. At the same time, even if a base class is virtual, we can still manipulate the object of the derived class through the pointer or reference of the base class type.

C ++ without virtual functions cannot be object-oriented. From a commercial point of view, object-oriented can make the system scalable and adaptive, but it will not reduce maintenance costs if only the C ++ class syntax is not object-oriented, in fact, it will increase the cost. Therefore, there is no virtual function, and the keyword virtual is the key.


 

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.