I 've been searching for a long time to find all the articles I want on the Internet. Because I have always had a question: what is the existence of a virtual table? Is it a class or an object? Where does a virtual pointer exist? Is it a class or an object? Finally, I find what I want in the first article.
1. overload in c ++ class
Take a look at the following code:
[Html]
# Include <iostream>
Using namespace std;
Class Vehicle
{
Public:
Vehicle (float speed, int total)
{
Vehicle: speed = speed;
Vehicle: total = total;
}
Void ShowMember ()
{
Cout <speed <"|" <total <endl;
}
Protected:
Float speed;
Int total;
};
Class Car: public Vehicle
{
Public:
Car (int aird, float speed, inttotal): Vehicle (speed, total)
{
Car: aird = aird;
}
Void ShowMember ()
{
Cout <speed <"|" <total <"|" <aird <endl;
}
Protected:
Int aird;
};
Void main ()
{
Vehicle a (120,4 );
A. ShowMember ();
Car B (180,110, 4 );
B. ShowMember ();
Cin. get ();
}
# Include <iostream>
Using namespace std;
Class Vehicle
{
Public:
Vehicle (float speed, int total)
{
Vehicle: speed = speed;
Vehicle: total = total;
}
Void ShowMember ()
{
Cout <speed <"|" <total <endl;
}
Protected:
Float speed;
Int total;
};
Class Car: public Vehicle
{
Public:
Car (int aird, float speed, inttotal): Vehicle (speed, total)
{
Car: aird = aird;
}
Void ShowMember ()
{
Cout <speed <"|" <total <"|" <aird <endl;
}
Protected:
Int aird;
};
Void main ()
{
Vehicle a (120,4 );
A. ShowMember ();
Car B (180,110, 4 );
B. ShowMember ();
Cin. get ();
} In c ++, the base class member functions can be reloaded by the derived classes. For objects of different classes, when calling the member functions of their classes, the system knows how to find members with the same name of the class. In the above Code, a. ShowMember () calls Vehicle: ShowMember (), while B. ShowMember () calls
[Html]
Car: ShowMemeber ().
# Include <iostream>
Using namespace std;
Class Vehicle
{
Public:
Vehicle (float speed, int total)
{
Vehicle: speed = speed;
Vehicle: total = total;
}
Void ShowMember ()
{
Cout <speed <"|" <total <endl;
}
Protected:
Float speed;
Int total;
};
Class Car: public Vehicle
{
Public:
Car (int aird, float speed, inttotal): Vehicle (speed, total)
{
Car: aird = aird;
}
Void ShowMember ()
{
Cout <speed <"|" <total <"|" <aird <endl;
}
Protected:
Int aird;
};
Void test (Vehicle & temp)
{
Temp. ShowMember ();
}
Void main ()
{
Vehicle a (120,4 );
Car B (180,110, 4 );
Test ();
Test (B );
Cin. get ();
}
Car: ShowMemeber ().
# Include <iostream>
Using namespace std;
Class Vehicle
{
Public:
Vehicle (float speed, int total)
{
Vehicle: speed = speed;
Vehicle: total = total;
}
Void ShowMember ()
{
Cout <speed <"|" <total <endl;
}
Protected:
Float speed;
Int total;
};
Class Car: public Vehicle
{
Public:
Car (int aird, float speed, inttotal): Vehicle (speed, total)
{
Car: aird = aird;
}
Void ShowMember ()
{
Cout <speed <"|" <total <"|" <aird <endl;
}
Protected:
Int aird;
};
Void test (Vehicle & temp)
{
Temp. ShowMember ();
}
Void main ()
{
Vehicle a (120,4 );
Car B (180,110, 4 );
Test ();
Test (B );
Cin. get ();
}
Objects a and B are distinguished as objects of the base class and derived class, while the form parameter of the function test is only a reference of the Vehicle class. According to the characteristics of class inheritance, the system regards the Car class object as a Vehicle class object. Because the Car class covers the Vehicle class, the definition of the test function is correct, the purpose of using the test function is to pass the references of different classes of objects and call the ShowMember member functions of different classes and overload them respectively, however, the running result of the program is unexpected. The system cannot tell whether the passed base class object is a derived class object, both the base class object and the derived class object call the ShowMember member function of the base class.
To solve this problem, we use polymorphism.
2. Virtual tables and virtual addresses in Polymorphism
Anyone familiar with C ++ should know that Virtual functions are implemented through a Virtual Table. V-Table for short. In this table, the primary table is the address table for a class virtual function. This table solves the inheritance and overwrite issues and ensures that it can reflect the actual functions.
[Html]
Class
{
Protected:
Virtual voidtest () {cout <"aaa" <endl ;}
Virtual voidtest1 () {cout <"df" <endl ;}
};
Class
{
Protected:
Virtual voidtest () {cout <"aaa" <endl ;}
Virtual voidtest1 () {cout <"df" <endl ;}
};
(1) sizeof (A) = 4, this 4 should be A pointer size, representing A virtual pointer, A virtual pointer is A function pointer, pointing to the position in the virtual function table, the virtual table contains the address of the virtual function.
(2) A; sizeof (a) = 4. The virtual pointer exists in each object, because the class is not a storage place.
(3) the C ++ compiler should ensure that the pointer to the virtual function table exists in the front of the object instance (this is to ensure the highest performance of the virtual function table-if there are multi-layer inheritance or ). This means that we can get this virtual function table through the address of the object instance, then we can traverse the function pointer and call the corresponding function.
(4) the virtual table is shared by the entire class. Its size depends on the number of virtual functions you define and the compiler policy. it usually exists somewhere in the memory and you don't need to worry about it.
Here I have another question, why is the following program equal to 1:
[Html]
Class
{
Protected:
Voidtest () {cout <"aaa" <endl ;}
Voidtest1 () {cout <"df" <endl ;}
};
Int main ()
{
Cout <sizeof (a) <endl;
Getchar ();
}
Class
{
Protected:
Voidtest () {cout <"aaa" <endl ;}
Voidtest1 () {cout <"df" <endl ;}
};
Int main ()
{
Cout <sizeof (a) <endl;
Getchar ();
}
3. virtual function table
(1) how to obtain the address of the virtual function table
Suppose we have a class like this:
[Html]
Class Base {
Public:
Virtual void f () {cout <"Base: f" <endl ;}
Virtual void g () {cout <"Base: g" <endl ;}
Virtual void h () {cout <"Base: h" <endl ;}
};
Class Base {
Public:
Virtual void f () {cout <"Base: f" <endl ;}
Virtual void g () {cout <"Base: g" <endl ;}
Virtual void h () {cout <"Base: h" <endl ;}
};
As mentioned above, we can use the Base instance to obtain the virtual function table. The following is the actual routine:
[Html]
Typedef void (* Fun) (void );
Base B;
Fun pFun = NULL;
Cout <"virtual function table address:" <(int *) (& B) <endl;
Cout <"virtual function table-first function address:" <(int *) * (int *) (& B) <endl;
// Invoke the first virtualfunction
PFun = (Fun) * (int *) (& B ));
PFun ();
Typedef void (* Fun) (void );
Base B;
Fun pFun = NULL;
Cout <"virtual function table address:" <(int *) (& B) <endl;
Cout <"virtual function table-first function address:" <(int *) * (int *) (& B) <endl;
// Invoke the first virtualfunction
PFun = (Fun) * (int *) (& B ));
PFun ();
The actual running results are as follows: (Windows XP + VS2003, Linux 2.6.22 + GCC 4.1.3)
Virtual function table address: 0012FED4
Virtual function table-first function address: 0044F148
Base: f
Through this example, we can see that we can forcibly convert & B into int * to obtain the address of the virtual function table. Then, the address of the first virtual function can be obtained again, that is, Base: f (), this is verified in the above program (the int * is forcibly converted to a function pointer ). Through this example, we can know that if you want to call Base: g () and Base: h (), the Code is as follows:
(Fun) * (int *) (& B) + 0); // Base: f ()
(Fun) * (int *) (& B) + 1); // Base: g ()
(Fun) * (int *) (& B) + 2); // Base: h ()