Why don't you call the virtual function __ function in the constructor

Source: Internet
Author: User

Let's look at a section of code that calls a virtual function directly in the constructor:

1 #include <iostream>
 2 
 3 class base
 4 {
 5 public:
 6     Base () {Foo ();}   < print 1
 7 
 8     virtual void Foo ()
 9     {         std::cout << 1 << std::endl;
One     }
; 
class Derive:public Base {public
:     Derive (): Base (), M_pdata (new int (2)) {}
  18     ~derive () {delete m_pdata;}     virtual void Foo ()         std::cout << *m_pdata << Std::endl;
Private:     int* m_pdata;
};
The 
int main ()
{     base* p = new Derive ();
to     delete p;     0;
33}

The results here will be printed: 1.

This indicates that line 6th executes Base::foo () instead of Derive::foo (), which means that a virtual function "does not work" in the constructor. Why.

When instantiating a derived class object, the base class part is constructed first, and then the derived class part is constructed. That is, when the derive object is created, the base constructor is called first, and the derive constructor is called.

When the base class part is constructed, the derived class is not yet fully created, and in some sense it is just a base class object. That is, when Base::base () executes the derive object is not fully created, it is treated as a base object instead of a derive object, so Foo is bound to base foo.

C + + is designed to reduce error and bug occurrences. Suppose the virtual function is still "in effect" in the constructor, that is, Foo () in Base::base (), and the call is Derive::foo (). When the Base::base () is invoked, the data in the derived class is m_pdata and the execution of Derive::foo () will cause the program to dereference an uninitialized address, resulting in unpredictable or even program crashes (access to illegal memory).

In summary: The base class part is constructed before the derived class part, and the data member in the derived class is not initialized when the base class constructor executes. If a virtual function call in a base class constructor is resolved to call a virtual function of the derived class, and the virtual function of the derived class accesses the uninitialized derived class data, it causes the program to have some undefined behavior and bugs.

For this, the General compiler will give some support. If you declare foo in a base class as a pure virtual function (see the following code), the compiler might: give the symbol an unresolved error (unresolved external symbol) at compile time with a warning or link. If you can generate an executable file, there must be an error at runtime. Because Foo in base::base () always calls Base::foo, at this point Base::foo only declares undefined. Most compilers can be identified when they are linked.

1 #include <iostream>
 2 
 3 class base
 4 {
 5 public:
 6     Base () {Foo ();}   < possible results: Compile warning, link error, run-time error
 7 
 8     virtual void Foo () = 0;
 9};
2 
class Derive:public base
{public
:     Derive (): Base (), M_pdata (new int ()) {}
  15     ~derive () {delete m_pdata;}     virtual void Foo ()         std::cout << *m_pdata << Std::endl;
Private:     int* m_pdata;
};
The 
int main ()
{     base* p = new Derive ();     delete p;
return     0;
30}

If the compiler can recognize this error invocation when compiling or linking, then our chances of making a mistake are greatly reduced. There are some less intuitive cases (see the code below), the compiler is not able to determine. In this case, it can generate an executable file, but an error occurs when the program runs.

 1 #include <iostream> 2 3 class Base 4 {5 Public:6   Base () {subtle ();}
 < Run-time error (pure virtual function call) 7 8 virtual void Foo () = 0;
9 void Subtle () {Foo ();} 10}; Class Derive:public Base {public:15 derive (): Base (), M_pdata (new int (2)) {} ~derive () {dele Te M_pdata; virtual void Foo () {std::cout << *m_pdata << Std::endl private:2
3 int* m_pdata;
24}; the int main () {

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.