In the introduction to c++, a question unfolds...inheritance and derivation, polymorphism and overloading

c++入门中,一道题展开的好多东西……权作记录

topic

Program analysis:

`
#include   <iostream>   
#include   <complex>   
using namespace   std;   

class Base   
{
    
       
public:   
	Base() {
    
    cout<<"Base-ctor"<<endl;}   
	~Base() {
    
    cout<<"Base-dtor"<<endl;}   
	virtual void f(int){
    
    cout<<"Base::f(int)"<<endl;}   
	virtual void f(double){
    
    cout<<"Base::f(double)"<<endl;}   
	virtual void g(int i=10){
    
    cout<<"Base::g()"<<i<<endl;}   
};  
 
class Derived : public Base   
{
    
       
public:   
	Derived() {
    
    cout<<"Derived-ctor" <<endl;}   
	~Derived(){
    
    cout<<"Derived-dtor"<<endl;}
	void f(complex<double>) {
    
     
		cout<<"Derived::f(complex)"<<endl;
	}
	void g(int i=20){
    
    
		cout<<"Derived::g()"<<i<<endl;
	}
};  
 
int main()   
{
    
       
	cout<<sizeof(Base)<<endl;
	cout<<sizeof(Derived)<<endl;
	
	Base b;   
	Derived d;
	cout<<endl;
	
	Base *pb=new Derived;
	cout<<endl; 

	b.f(1.0);   
	d.f(1.0);   
	pb->f(1.0);
	cout<<endl; 
	
	b.g();   
	d.g();   
	pb->g();
	cout<<endl; 
	
	delete   pb;   
	return 0;
}  
`

operation result

operation result

analyze

Obviously Base is the base class, and Derived is the derived class, both of which define constructors and destructors as well as their respective member functions and virtual functions used in the base class.

  1. sizeof()
  • See the main function, what is sizeof(class)?

    sizeof 是一个关键字,它是一个编译时运算符,用于判断变量或数据类型的字节大小。
    可用于获取类、结构、共用体和其他用户自定义数据类型的大小。
    形如sizeof (data type)
    

    So, sizeof(class) is used to calculate the size of the class.

    • Looking at the running results again, both sizeof(type_name) are 8. Why?

        成员函数(包括静态与非静态,虚函数也是成员函数)和静态数据成员都不占用类对象的存储空间
        如有虚函数会生成虚函数表,并在该类型的每一个实例中添加指向虚函数表的指针(一个虚函数表(一到多个虚函数)只有一个指针)
        32位机器中一个指针占4字节空间,64位机器中一个指针占8字节空间
        普通继承的父类和子类共用一个虚函数表,但虚继承子类和父类各有自己的一个虚表指针
      

    Obviously, both Base and Derived have only one virtual table pointer, so both get sizeof as 8.

    According to the 7th point of the following blog,

    	在普通继承下,不管是子类还是父类包含虚函数,子类的sizeof=sizeof(基类数据成员)+sizeof(派生类数据成员)+sizeof(指针)
    

    https://blog.csdn.net/szchtx/article/details/10254007

    • other

        只要基类的成员函数是虚函数,派生类的同名函数(参数相同,返回值类型相同),函数体不同,不管有没有显式声明virtual都是虚函数。
      
    • other

    https://blog.csdn.net/e2788666/article/details/118070051

    sizeof also involves an offset issue, if you are interested, you can learn from the following

    https://baike.baidu.com/item/sizeof%28%29/10474327?fr=aladdin

  1. Continue to look at the code Base *pb=new Derived. From the output, we can see that the base class is constructed first, and then the derived class is constructed. Why, this is related to the new keyword

     new一个子类对象,其实还是调用子类的构造函数,调用子类的构造函数又还是先调用基类构造再调用派生类构造。
     而调用派生类构造函数的顺序又是先调用基类再到派生类,所以如是输出。
     new Derived等价于Derived x(指某实例名)
     这个代码实质是new一个派生类对象赋给基类指针(基类指针指向派生类对象)
    
  2. Look at the piece of code that calls the f() function and its corresponding output.
    This involves the problem of functions with the same name - overloading, hiding, and overriding.
    When the parameters of the base class Base::f() and the derived class Derived::f() are changed When they are of the same type (both are double or both are complex), it constitutes a function coverage with the same name, which function body to call is determined according to the type of the object pointed to by the pointer, where pb points to a derived class object, so calling a derived class function with the same name but different parameters
    constitutes Hiding, after hiding, look at the pointer type, the parent class still calls the function of the parent class, and the subclass still calls the function of the subclass. See
    below for details

    https://blog.csdn.net/qq_43435084/article/details/90115244

    https://blog.csdn.net/yanguilaiwuwei/article/details/41347255

    https://blog.csdn.net/choudan8888/article/details/98098204

    https://blog.csdn.net/m0_62656812/article/details/121965526

  3. The code to the g() method and its corresponding output. Why does the value of the formal parameter i output by the method of the derived class called by pb belong to the base class?
    //The derived class function is called but the default value of the formal parameter of the function with the same name in the base class is output.
    //The pre-set parameters are statically set, while the type of the function to be called is determined dynamically.
    //For virtual functions, the compilation system will determine the value of the default parameter according to the type of the object of the called function at compile time.
    //The default value is different, at this time the compilation system takes the one encountered first.
    See below for details

    https://blog.csdn.net/qq_26501341/article/details/116264566

  4. Look at delete pb again; this line of code and its output
    /using the pointer of the base class to point to the object will cause problems when it is destructed, because the derived class object releases the derived class first, and then releases the base class (correct method),
    and use the base class pointer to point to the derived class object, and only the base class is destructed when destructed (wrong way), resulting in the part of the derived class not being released, becoming zombie memory or memory leak.
    Therefore, use the base class pointer to point to the derived class object, and use the virtual destructor to make the base class pointer point to the derived class (the function of virtual: call the corresponding type function according to the actual type of the object), so that the memory can be released manually
    delete , you can call the destructor of the derived class, which automatically calls the destructor of the base class.

emmm, come here first, write for the first time, a bit numb

Guess you like

Origin blog.csdn.net/weixin_50624398/article/details/124234659