标签:
#include<<span style="font-size:14px;">iostream</span>> using namespace std; class Base { public: Base() {} ~Base() {} private: int _pri; protected: int _pro; public: int _pub; }; class Derive : public Base { public: Derive() {} ~Derive() {} private: int _dPri; protected: int _dPro; public: int _dPub; }; int main() { cout << sizeof(Base) << endl;//12=4+4+4 cout << sizeof(Derive) << endl;//24,派生类的大小包含了基类的大小和自己的大小 return 0; }
继承关系和访问限定符:
class Base { public: Base() {} ~Base() {} private: int _pri; protected: int _pro; public: int _pub; }; class Derive :public Base { public: Derive() {} ~Derive() {} void Display() { cout << "_pri=" << _pri << endl;//error基类的私有成员在派生类中不能被访问 cout << "_pri=" << _pro << endl; cout << "_pri=" << _pub << endl; cout << "_dpri=" << _dpri << endl; cout << "_dpri=" << _dpri << endl; cout << "_dkpri=" << _dpri << endl; } private: int _dpri; protected: int _dpro; public: int _dpub; }; int main() { Derive d; d._pri = 10;//error d._pro = 20;//error
d._pub = 30;
d._dpri = 20;//error d._dpro = 20;//error d._dpub = 20; }
<span style="font-size:12px;">总结:</span>
在派生类中如果没有显示定义类的六个成员函数,编译器系统则会默认合成这六个默认的成员函数
<span style="font-size:12px;">class Base { public: Base() { cout << "Base()" << endl; } ~Base() { cout << "~Base()" << endl; } private: int _pri; protected: int _pro; public: int _pub; }; class Derive :public Base { public: Derive() { cout << "Derive()" << endl; } ~Derive() { cout << "~Derive()" << endl; } private: int _dpri; protected: int _dpro; public: int _dpub; }; int main() { { Derive d; } getchar(); return 0; }</span>
继承关系中构造函数调用的顺序:基类构造函数 =》派生类中对象构造函数 =》派生类构造函数体
继承关系中析构函数调用的顺序:派生类析构函数 =》派生类包含成员对象析构函数 =》基类析构函数
说明: 1、基类没有缺省构造函数,派生类必须要在初始化列表中显式给出基类名和参数列表。
2、基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数。
3、基类定义了带有形参表构造函数,派生类就一定定义构造函数。
默认构造函数:指调用时无需提供参数的构造函数,因此:它可以是没有参数的,也可以是所有参数都有默认值的,两者取其一,否则有二义性。
编译器会合成默认(缺省)构造函数:1.当类中有类类型的成员,且类成员有默认的构造函数;
2.当基类有默认构造函数时,派生类没有构造函数;
3.当类中有虚函数或类派生链中有虚函数时;
4.当类采用虚继承方式时。
调用拷贝构造函数:1.用一个对象初始化另一个对象时,且是同类对象;(对象构建对象)
2.当函数的参数是对象,通过对象调用函数时,参数的拷贝会调用拷贝构造函数;(值传参)
3.当函数的返回值是对象,调用函数时,返回一个对象会调用拷贝构造函数。(值返回值)
编译器会合成拷贝构造函数:1.当类中有类类型的成员,且类成员有拷贝构造函数;
2.当基类有拷贝构造函数时,派生类没有拷贝构造函数;
3.当类中有虚函数时;
4.当类采用虚继承方式时。
继承体系中的作用域:
1.在继承体系中基类和派生类是两个不同作用域。
2.子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以使用 基类::基类成员 访问)--隐藏 --重定义
3.注意在实际中在继承体系里面最好不要定义同名的成员。
继承与转换--赋值兼容规则--public继承:1.子类对象可以赋值给父类对象(切割/切片)
2.父类对象不能赋值给子类对象
3.父类的指针/引用可以指向子类对象
4.子类的指针/引用不能指向父类对象(可以通过强制类型转换完成)
class Base { public: Base(int data) {} ~Base() {} private: int _pri; protected: int _pro; public: int _pub; static int count; }; int Base::count = 0; class Derive : public Base { public: Derive() : Base(20) {} ~Derive() {} private: int _dPri; protected: int _dPro; public: int _dPub; int _pri; }; int main() { Derive d; Base b(0); b = d; d = b;//error,父类对象不能赋值给子类 Base* pBase = &d; Derive *pD = (Derive*)&b;//通过强制类型转换可以赋值 return 0; }
友元与继承:友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。
继承与静态成员:基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例。
单继承:一个子类只有一个直接父类。
多继承:一个子类至少有两个父类。
菱形继承:会产生二义性和数据冗余问题。
<span style="font-family:SimSun;font-size:12px;">class Person { public: string _name; // 姓名 }; class Student : public Person { protected: int _num; //学号 }; class Teacher : public Person { protected: int _id; // 职工编号 }; class Assistant : public Student, public Teacher { protected: string _majorCourse; // 主修课程 }; void Test() { // 显示指定访问哪个父类的成员 Assistant a; a.Student::_name = "xxx"; a.Teacher::_name = "yyy"; }</span>
<span style="color:#ff0000;">为了解决菱形继承的二义性和数据冗余问题,使用虚继承</span>。
<pre class="cpp" name="code">class B { public: int data1; }; class B1 : virtual public B { public: int data2; }; class B2 : virtual public B { public: int data3; }; class D :public B1, public B2 { public: void FunTest() { B1::data1 = 0x01; data2 = 0x02; B2::data1 = 0x03; data3 = 0x04; data4 = 0x05; cout << this << endl; cout << &B1::data1 << endl; cout << &data2 << endl; cout << &B2::data1 << endl; cout << &data3 << endl; cout << &data4 << endl; cout << data1 << endl; } int data4; }; int main() { cout << sizeof(B) << endl; cout << sizeof(B1) << endl; cout << sizeof(B2) << endl; cout << sizeof(D) << endl; D d; d.FunTest(); getchar(); return 0; }
<img src="http://img.blog.csdn.net/20160409171053173?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
<img src="http://img.blog.csdn.net/20160409171114078?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
</pre></p><p></p><pre>
标签:
原文地址:http://blog.csdn.net/lihui0217/article/details/51105459