zoukankan      html  css  js  c++  java
  • C++学习笔记-继承中的构造与析构

    C++存在构造函数与析构函数,继承中也存在构造和析构函数。继承中的构造和析构函数与普通的构造析构有细微差别。

    赋值兼容性原则

    #include "iostream"
    using namespace std;
    
    class Parent
    {
    public:
    	void printP()
    	{
    		printf("父类
    ");
    	}
    protected:
    	int a;
    	int b;
    };
    
    class Child : public Parent
    {
    public:
    	Child()
    	{
    		a = 0; b = 0; c= 0;
    	}
    	void printC()
    	{
    		printf("子类
    ");
    	}
    protected:
    private:
    	int c;
    };
    
    void howToPrint(Parent *p)
    {
    	p->printP();
    }
    
    void howToPrint2(Parent &p)
    {
    	p.printP();
    }
    
    void main()
    {
    	Parent p1;
    	p1.printP();
    	Child c1;
    	c1.printC();
    
    	Parent *base = NULL;
    	base = &c1;
    	//可以把子类对象赋给基类指针
        //子类就是一种特殊的父类
    	base->printP();
    
    	Parent &myp = c1;
    	myp.printP();
    
    	//测试父类指针,做函数参数
    	howToPrint(&p1);
    	howToPrint(&c1);
    
    	//测试父类引用,做函数参数
    	howToPrint2(p1);
    	howToPrint2(c1);
    
    	//可以用子类对象来初始化父类对象
    	Parent p3 = c1;
    
    	system("pause");
    }
    
    • 子类对象可以当作父类对象使用
    • 子类对象可以直接赋值给父类对象
    • 子类对象可以直接初始化父类对象
    • 父类指针可以直接指向子类对象
    • 父类引用可以直接引用子类对象
      总结:子类就是特殊的父类 (base *p = &child;)

    继承中的对象模型

    • 类在C++编译器的内部可以理解为结构体
    • 子类是由父类成员叠加子类新成员得到的

    继承中构造和析构

    • 在子类对象构造的时,需要调用父类构造函数对其继承得来的成员进行初始化
    • 在子类对象析构的时,需要调用父类析构函数对其继承得来的成员进行清理

    继承中的构造析构调用原则

    class Parent
    {
    public:
    	Parent(int a)
    	{
    		···;
    	}
    ···
    };
    
    class Child : public Parent
    {
    public:
    	Child() : Parent(10)
    	{
    		···;
    	}
    ···
    };
    
    • 子类对象在创建时会首先调用父类的构造函数
    • 父类构造函数执行结束后,执行子类的构造函数
    • 当父类的构造函数有参数时,需要在子类的初始化列表中显示调用
    • 析构函数调用的先后顺序与构造函数相反

    继承与组合混搭情况下,构造和析构调用原则

    #include <iostream>
    using namespace std;
    
    class Object
    {
    public:
    	Object(const char* s)
    	{
    		cout<<"Object()"<<" "<<s<<endl;
    	}
    	~Object()
    	{
    		cout<<"~Object()"<<endl;
    	}
    };
    
    class Parent : public Object
    {
    public:
    	Parent(const char* s) : Object(s)
    	{
    		cout<<"Parent()"<<" "<<s<<endl;
    	}
    	~Parent()
    	{
    		cout<<"~Parent()"<<endl;
    	}
    };
    
    class Child : public Parent
    {
    protected:
    	Object o1;
    	Object o2;
    public:
    	Child() : o2("o2"), o1("o1"), Parent("Parameter from Child!")
    	{
    		cout<<"Child()"<<endl;
    	}
    	~Child()
    	{
    		cout<<"~Child()"<<endl;
    	}
    };
    
    void run()
    {
    	Child child;
    }
    
    int main(int argc, char *argv[])
    {
    	cout<<"demo05_extend_construct_destory.cpp"<<endl;
    	run();
    
    	system("pause");
    	return 0;
    }
    

    原则:先构造父类,再构造成员变量、最后构造自己;先析构自己,在析构成员变量、最后析构父类。先构造的对象,后释放

    继承中的同名成员变量处理方法

    • 当子类成员变量与父类成员变量同名时
    • 子类依然从父类继承同名成员
    • 在子类中通过作用域分辨符::进行同名成员区分
    • 同名成员存储在内存中的不同位置
  • 相关阅读:
    数据库使用--MySQL: InnoDB 还是 MyISAM?
    数据库使用3--索引系列
    数据库使用1--注意事项
    数据库使用2--索引系列
    学习FFmpeg API
    几种常见 容器 比较和分析 hashmap, map, vector, list ...hash table
    tiny中文乱码问题,不过仅适用于windows,所以xml不可以出现中文
    【NumPy】numpy数组类型
    【1.1】Scrapy抓取4步走、新建项目
    django+markdown
  • 原文地址:https://www.cnblogs.com/cj5785/p/10664724.html
Copyright © 2011-2022 走看看