继承中的构造函数和析构函数
继承中的构造和析构顺序
- 子类创建对象时,先调用父类的构造,然后调用自身构造
- 析构顺序与构造顺序相反
- 子类不会继承父类的构造函数和析构函数
- 如果父类中没有合适默认构造,那么子类可以利用初始化列表的方式显示的调用父类的其它构造
#include<iostream>using namespace std;class Base
{
public:Base(){cout << "Base默认构造函数调用" << endl;}~Base(){cout << "Base的析构函数的调用" << endl;}
};
//子类会继承父类的成员属性,成员属性
//但是 子类 不会继承 父类 构造函数 和 析构函数
//只有父类自己知道如果构造和析构自己的属性,而子类不知道class Son :public Base
{
public:Son(){cout << "Son默认构造函数的调用" << endl;}~Son(){cout << "Son的析构函数的调用" << endl;}
};class Base2
{
public:Base2(int a){this->m_A = a;cout << "有参构造函数调用" << endl;}int m_A;
};class Son2 :public Base2
{
public:Son2(int a) : Base2(10) //利用初始化列表方式 显示调用 有参构造{}
};void test02()
{Son2 s2(1000);
}void test01()
{//Base b1;Son s1;
}int main()
{test01();system("pause");return 0;
}
注意:
- 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函 数,则必须在派生类构造函数的初始化列表阶段显示调用。
- 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。
- 派生类的operator=必须要调用基类的operator=完成基类的复制。
- 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类 对象先清理派生类成员再清理基类成员的顺序。
- 派生类对象初始化先调用基类构造再调派生类构造。
- 派生类对象析构清理先调用派生类析构再调基类的析构
继承中同名成员
继承中的同名处理
- 成员属性 直接调用先调用子类,如果想调用父类,需要作用域
- 成员函数 直接调用先调用子类,父类的所有版本都会被隐藏,除非显示用作用域运算符去调用
#include<iostream>using namespace std;class Base
{
public:Base(){m_A = 100;}void fun(){cout << "Base func的调用" << endl;}void fun(int a){cout << "Base func(int a)的调用" << endl;}int m_A;
};class Son :public Base
{
public:Son(){m_A = 200;}void fun(){cout << "Son func的调用" << endl;}int m_A;
};void test01()
{Son s1;cout << s1.m_A << endl;//想调用 父类中的m_Acout << s1.Base::m_A << endl;//s1.fun(10);//调用父类的funcs1.Base::fun();
}
//如果父类和子类拥有同名的函数 属性 子类不会覆盖父类成员
//如果子类与父类的成员函数名称相同 子类会把父类的所有同名版本都隐藏掉
//想调用父类的方法,必须加作用域int main()
{test01();system("pause");return 0;
}
注意:
1. 在继承体系中基类和派生类都有独立的作用域。
2. 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定 义。(在子类成员函数中,可以使用 基类::基类成员 显示访问)
3. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。
4. 注意在实际中在继承体系里面最好不要定义同名的成员。
继承中静态成员
- 类似非静态成员函数处理
- 如果想访问父类中的成员,加作用域即可
#include<iostream>using namespace std;class Base
{
public:static void func(){cout << "Base func()" << endl;}static void func(int a){cout << "Base func(int a)" << endl;}static int m_A;
};
int Base::m_A = 10;class Son :public Base
{
public:static void func(){cout << "Son func()" << endl;}static int m_A;
};int Son::m_A = 20;
//静态成员属性 子类可以继承下来
void test01()
{cout << Son::m_A << endl;//访问父类的m_Acout << Base::m_A << endl;Son::func();//访问父类中同名的成员函数Son::Base::func();
}int main()
{test01();system("pause");return 0;
}
注意:
- 静态成员和非静态成员都可以被继承到派生类中
- 如果重新定义一个静态成员函数,所有在基类中的其他重载函数会被隐藏
- 如果我们改变基类中一个函数的特征,所有使用该函数的基类版本都会被隐藏