前端做学校网站教务,32强世界排名,网站建设视频直播功能表,手机app下载安装到手机继承 1、概念#xff1a;
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段#xff0c;它允许程序员在保持原有类特性的基础上进行扩展#xff0c;增加功能。这样产生新的类#xff0c;称派生类。继承呈现了面向对象程序设计的层次结构#xff0c;体…
继承 1、概念
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段它允许程序员在保持原有类特性的基础上进行扩展增加功能。这样产生新的类称派生类。继承呈现了面向对象程序设计的层次结构体现了由简单到复杂的认知过程。
一个新类从已有的类中获得其已有的特性称为继承被继承的称为父类Base class或基类新产生的类称为派生类或子类。 2、访问限定符与继承关系 类的成员有三种访问限定符public公有、protected保护、
private私有 继承的方式public公有继承、protected保护继承、
Private私有继承 3、继承的方式
继承权限规则表 继承方式 基类的public成员 基类的protected成员 基类的private成员 继承引起的访问控制变化 Public Public Protected 不可见 基类成员在派生类中访问权限不变 Protected Protected Protected 不可见 基类的非私有成员成为子类的保护成员 Private Private Private 不可见 基类的所有成员成为子类的私有成员 基类
class Base
{
public: Base() :pub(1) ,pro(2) ,pri(3) {} public: int pub; protected: int pro; private: int pri; }; 1公有继承采用公有继承时基类成员的访问权限在派生类中不变
class Derived1:public Base
{
public: Derived1() :d_pub(4) ,d_pro(5) ,d_pri(6) {} void SetData() { pub 0; pro 0; pri 0; //子类无法访问基类的私有成员 } public: int d_pub;
protected: int d_pro;
private: int d_pri;
}; void FunTest()
{ Base b; b.pub 1; b.pro 2; b.pri 3; //类外无法访问类的保护、私有成员 Derived1 d1; d1.pub 1; d1.pro 2; d1.pri 3; //子类对象无法访问基类的保护、私有成员 d1.d_pub 4; d1.d_pro 4; d1.d_pri 4; //类外无法访问类的保护、私有成员
} 2保护继承基类的公有、保护成员成为派生类的保护成员。 class Derived2:protected Base
{
public: Derived2() :d_pub(4) ,d_pro(5) ,d_pri(6) {} void SetData() { pub 0; //成为子类的保护成员 pro 0; pri 0; //子类无法访问基类的私有成员 } public: int d_pub;
protected: int d_pro;
private: int d_pri;
}; void FunTest()
{ Base b; b.pub 1; b.pro 2; b.pri 3; //类外无法访问类的保护、私有成员 Derived2 d2; d2.pub 1; //成为子类的保护成员无法访问 d2.pro 2; d2.pri 3; //子类对象无法访问基类的保护、私有成员 d2.d_pub 4; d2.d_pro 4; d2.d_pri 4; //类外无法访问类的保护、私有成员
}
3私有继承
class Derived3:private Base
{
public: Derived3() :d_pub(4) ,d_pro(5) ,d_pri(6) {} void SetData() { pub 0; //成为子类的私有成员 pro 0; pri 0; //子类无法访问基类的私有成员 } public: int d_pub;
protected: int d_pro;
private: int d_pri;
}; void FunTest()
{ Base b; b.pub 1; b.pro 2; b.pri 3; //类外无法访问类的保护、私有成员 Derived3 d3; d3.pub 1; //成为子类的私有成员无法访问 d3.pro 2; d3.pri 3; //子类对象无法访问基类的保护、私有成员 d3.d_pub 4; d3.d_pro 4; d3.d_pri 4; //类外无法访问类的保护、私有成员
} 2、 总结 1 类的保护成员和私有成员在类外部都不可访问基类的私有成员在派生类都不可访问。 2 public继承是一个接口继承保持is-a原则每个父类可用的成员对子类也可用因为每个子类对象也都是一个父类对象。 例如有一个Horse类可以保存关于马的所有信息身高体重等等那么我们就可以从Horse类中派生出白马类白马类包含所有Horse类的成员在白马类中可以新增关于白马的成员这个成员通常不用于Horse类。 class Horse
{
public: int Tall; int Weight;
};
classWhiteHorse:public Horse
{
public: int Color;
};
WhiteHorse是Horse的一个子类包括了Horse类的所有成员is_a是一种关系 3 protetced/private继承是一个实现继承基类的部分成员并非完全成为子类接口的一部分是 has-a 的关系原则所以非特殊情况下不会使用这两种继承关系在绝大多数的场景下使用的都是公有继承。 实现继承的主要目标是代码重用我们发现类B和类C存在同样的代码因此我们设计了一个类 A用于存放通用的代码基于这种思路的继承称为实现继承。
基类的成员在派生类中是私有的基类方法将不会成为派生对象公有接口的一部分但可以在派生类的成员函数中使用它们基类方法将不会成为派生对象公有接口的一部分但可以在派生类的成员函数中使用它们。 class Banana
{..};
class Lauch
{
private:
classBanana; ......
}; 4 基类的 private 成员在派生类中是不能被访问的如果基类成员不想在类外直接被访问但需要在派生类中能访问就定义为 protected 。可以看出保护成员限定符是因继承才出现的。 5 使用关键字class时默认的继承方式是private使用struct时默认的继承方式是public不过最好显示的写出继承方式。 3、 派生类的默认成员函数 在继承关系里面在派生类中如果没有显示定义这六个成员函数编译系统则会默认合成这六个默认
的成员函数。 1 构造函数调用顺序
进入子类的构造函数——调用基类构造函数——执行子类构造函数
说明
1、基类没有缺省构造函数派生类必须要在初始化列表中显式给出基类名和参数列表。
2、基类没有定义构造函数则派生类也可以不用定义全部使用缺省构造函数。
3、基类定义了带有形参表构造函数派生类就一定定义构造函数 2 析构函数调用顺序
派生类析构函数——派生类包含成员对象的析构函数——基类析构函数
class Base
{
public: Base() { coutBase()endl; } Base(int b, int r, int i) :pub(1) ,pro(2) ,pri(3) { coutBase(int , int , int)endl; } ~Base() { cout~Base()endl; }
public: int pub;
protected: int pro;
private: int pri;
};
class Derived3:public Base
{
public: Derived3() { coutDerived3()endl; } Derived3(int d1, int d2, int d3) :Base(d1, d2, d3) { d_pub d1; coutDerived3() ----d_pubd_pubendl; } ~ Derived3() { cout~Derived3()endl; }
public: int d_pub;
protected: int d_pro;
private: int d_pri;
};
void FunTest()
{ Derived3 d0; Derived3 d3(1, 2, 3);
} 4、即成体系中的作用域
1在继承体系中基类和派生类是两个不同作用域。
2 子类和父类中有同名成员子类成员将屏蔽父类对成员的直接访问。在子类成员函数中可以使用 基类::基类成员 访问--隐藏 --重定义
3 注意在实际中在继承体系里面最好不要定义同名的成员 5、继承与转换--赋值兼容规则public继承
1子类对象可以赋值给父类对象切割/切片
2父类对象不能赋值给子类对象
3父类的指针/引用可以指向子类对象
4子类的指针/引用不能指向父类对象可以通过强制类型转换完成
class Base
{
public: Base() { coutBase()endl; } Base(int b, int r, int i) :pub(1) ,pro(2) ,pri(3) { coutBase(int , int , int)endl; } ~Base() {cout~Base()endl;} public: int pub; protected: int pro; private: int pri;
};
class Derived:public Base
{
public: Derived() { coutDerived3()endl; } Derived(int d1, int d2, int d3) :Base(d1, d2, d3) { d_pub d1; coutDerived()endl; } ~ Derived() { cout~Derived()endl; }
public: int d_pub;
protected: int d_pro;
private: int d_pri;
}; void FunTest()
{ Base b0; Base b1(1, 2, 3); Base* pBase; Derived d0; Derived d1(4, 5, 6); Derived* pDerived; b0 d0; //子类对象可以赋值给父类对象 b1 d1; d0 bo; // 父类对象不能赋值给子类对象 d1 b1; pBase d0; //父类的指针/引用可以指向子类对象 pBase d1; Base _b0 d0; Base _b1 d1; //父类的指针/引用可以指向子类对象 pDerived b0; Derived b1;//子类的指针/引用不能指向父类对象 pDerived (Derived *)b1; //可以使用的强制类型转换使子类的指针/引用指向父类对象 } 6、友元与继承
友元关系不能继承也就是说基类友元不能访问子类私有和保护成员。
class Base
{
public: Base() { pub 10; pro 10; pri 10; coutBase()endl; } ~Base() { cout~Base()endl; }
public: int pub;
protected: int pro;
private: int pri; friend void show();
};
class Derived:public Base
{
public: Derived() { d_pri 10 ; coutDerived3()endl; }
private: int d_pri;
};
void show()
{ Base b; coutb.priendl; //友元函数可以访问基类的私有成员 Derived d; coutd.d_priendl; //友元函数不能继承基类的友元函数不可以访问子类的私有成员
} 7、继承的类型
1单继承
class A
{
public: int data1;
} ;
class B :public A
{
public: int data2;
} ; 2多继承
class A
{
public: int data1;
} ;
class B
{
public: int data2;
} ; class C :public A ,public B
{
public: int data3;
} ; 3 菱形继承 class A
{
public: int data1;
} ;
class B: public A
{
public: int data2;
} ; class C:public A
{
public: int data3;
} ;
class D:public B,public C
{
public: int data4;
} ; D类的对象中存在两份A对象成员菱形继承存在二义性和数据冗余问题 8、虚继承--解决菱形继承的二义性和数据冗余的问题 class A
{
public: int data1; } ; class B: virtual public A
{
public: int data2;
} ; class C: virtual public A
{
public: int data3;
} ; class D:public B,public C
{
public: int data4;
} ; void FunTest() { D d; d.data1 1; d.data2 2; d.data3 3; d.data4 4; coutsizeof(B)endl;//12 coutsizeof(D)endl;//24
//0x0098F73C 000ecc88 00000002 000ecc94 00000003 00000004 00000001 } 1虚继承解决了在菱形继承体系里面子类对象包含多份父类对象的数据冗余浪费空间的问题。
2虚继承体系看起来好复杂在实际应用我们通常不会定义如此复杂的继承体系。一般不到万不得已都不要定义菱形结构的虚继承体系结构
因为使用虚继承解决数据冗余问题也带来了性能上的损耗。 就写到这了有什么不对的大家指正哈