目录
三、struct(结构体) 与 class(类) 在继承中的区别
4.7.4 问题一:那如果把上述代码中的参数列表初始化改为如下;会不会改变?
继承(inheritance) 机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础,上进行扩展,增加功能。这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构。体现了由简单到复杂的认识过程。百度百科(继承)
通过继承(inheritance)的机制可对类(class) 分层,提供类型/子类型的关系。
C+ +通过类派生(class derivation)的机制来支持继承。被继承的类称为基类(base class)或超类(superclass),新产生的类为派生类(derived class)或子类(subclass) 。基类和派生类的集合称作类继承层次结构(hierarchy) 。
class 派生类名:访问限定符 基类名1《,访问限定符 基类名2,.....访问限定符 基类名n》
{
private:
// 成员表1
// 派生类增加或替代的私有成员
public:
// 成员表2
// 派生类增加或替代的公有成员
protected:
// 成员表3
// 派生类增加或替代的保护成员
};//分号不可少
- class Person {
- private:
- char IdPerson[19]; // 编号
- char Name[20]; //姓名
-
- public:
- Person() { IdPerson[0] = '\0'; Name[0] = '\0'; }
- Person(char* id, char* name) {
- strcpy(IdPerson, id);
- strcpy(Name, name);
- }
- ~Person(){};
- void PrintPersonInfo()const {
- cout << "编号" << IdPerson << '\n' << "姓名:" << Name << endl;
- }
- };
- class Student : public Person
- {
- private:
- char snum[10];
- float grade;
- public:
- Student():Person(){}
- Student(char* id, char* name, char* sn) :Person(id, name) {
- strcpy(snum, sn);
- grade = 0.0;
- }
- ~Student(){}
- void PrintStudentInfo()const {
- PrintPersonInfo();
- cout << "学号: " << snum << "\n" << "成绩: " << grade << endl;
- }
- void SetGrade(float ft) {
- grade = ft;
- }
- };
总结:派生反映了事物之间的联系,事物的共性与个性之间的关系。派生与独立设计若干相关的类, 前者工作量少,复的部分可以从基类继承来,不需要单独编程。
具体实现如下:
- class Object {
- public:
- int value;
- int num;
- public:
- Object(int x = 0, int y = 0) :value(x), num(y) {
- cout << "Create Object :" << this << endl;
- }
- };
- class Base :public Object {
- public:
- int sum;
- int fib;
- public:
- Base(int a = 0, int b = 0) :sum(a), fib(b) {
- cout << "Create Base :" << this << endl;
- }
- };
- int main() {
- Base base1;
- }
如上图可以把Base派生类分为三部分,如下图:
所以对于派生类来说有三个成员:隐藏基类对象、sum、flag成员。
探讨各种继承关系之间的派生类对基类成员的访问属性;可以设计如下代码 ;用派生类的fun函数去调用基类的成员;其中 ax是私有成员 ay 保护成员 az是公有成员
类A如下所示:
- class A {
- private:
- int ax;
- protected:
- int ay;
- public:
- int az;
- public:
- A() { ax = ay = az = 0; }
- };
类B如下所示:
- class B
- {
- private:
- int bx;
- protected:
- int by;
- public:
- int bz;
- public:
- B() { bx = by = bz = 1; }
- void fun() {
- ax = 10; ay = 20; az = 30;
- }
- };
公有继承:
在继承中;不管那种继承方式私有成员在类内类外都不可访问;
假设 继承的派生类中含有基类的对象,例如如上派生类代码改为:
- class B :public A
- {
- private:
- int bx;
- A a;
- protected:
- int by;
- public:
- int bz;
- public:
- B() { bx = by = bz = 1; }
- void fun() {
- //ax = 10; ay = 20; az = 30;
- //a.ax = 15; a.ay = 25; a.az = 35;
- }
- };
内存图:
在私有属性中中定义;
在保护属性中定义:
在公有属性中:
在派生类中声明基类的具有名对象;无论该对象处于什么属性中;只能访问具有名对象的公有属性;
如果在派生类外的函数中访问派生类的属性会出现什么情况;例如在主函数(main)中给派生类对象赋值会出现什么结果?那种通过不了?为什么? 如果
主函数如图所示:
- int main() {
- B b;
- b.bz - 100;
- b.az - 100;
- b.ay - 100;
- b.a.az - 100;
- b.a.ay - 100;
- return 0;
- }
情况一:A a在派生类的公有属性中:派生类公有继承基类
情况二:派生类私有继承基类
情况三:将A a定义在保护和私有中A a将都不可访问;
外部函数可以访问类中的公有成员,可以访问公有继承中的公有成员,可以访问公有成员对象中的公有成员。
三层继承其实和两层继承差不多;理解好其中的关系即可;现在设计三个类;
类A:
- class A {
- private: int ax;
- protected: int ay;
- public: int az;
- public:
- A() { ax = ay = az = 0; }
- };
类B:
- class B
- {
- private: int bx;
- protected: int by;
- public: int bz;
- public: B() { bx = by = bz = 1; }
- };
类C:
- class C
- {
- private: int cx;
- protected: int cy;
- public: int cz;
- };
假设我们改变其中的继承关系会怎样影响类C中的的访问权限?
情况一:B公有继承A;C公有继承B类;
内存图:
fun函数中都能访问;但是A类和B类的私有成员不能访问;
情况二:将B类公有继承A类改为私有继承A类会怎样;
情况三: 将B类私有继承A类改为保护继承A类会怎样;
在多层继承中;派生类能否访问基类的对象成员;在于基类继承的基类成员是什么属性;如果基类继承私有继承;那么在基类的成员属性就为基类的私有成员;而私有成员被继承下来是不可访问的;
看如下代码的运行;思考运行结果ax=100是赋值给基类A还是派生类B;
- class A
- {
- protected:
- int ax;
- public:
- A() :ax(0) {}
- };
- class B :public A
- {
- private:
- int ax;
- public:
- B():ax(10){}
- void fun() {
- ax = 100;
- }
- };
- int main() {
- B b;
- b.fun();
- }
内存图:
那如果调用fun()函数了;我们都知道;会首先构建基类对象对象,那赋值是不是也先给基类对象赋值?
如果派生类与基类有相同的函数名字或者对象名字;派生类会访问自己的对象(就近原则);或者理解为编译期时候派生类对象隐藏了基类同名对象;所谓同名隐藏;
那怎么可以访问了?回答:假设类的作用域;
在继承中,派生类对象是否可以给基类对象赋值?
- class Object
- {
- private:
- int value;
- public:
- Object(int x = 10) :value(x) {}
- ~Object() {}
- };
- class Base :public Object {
- private:
- int num;
- public:
- Base(int x = 0) :num(x), Object(x + 10) {}
- ~Base() {};
- };
如果main函数作如下处理会不会改变基类的对象值?
- Object obja(100);
- Base s1(10);
派生类在初始化时,通过参数列表改变基类的值,会发生切片现象;但是必须在公有继承之下;
- class Base :public Object {
- private:
- int num;
- public:
- Base(int x = 0) :num(x)
- {
- Object(x + 10);
- }
- ~Base() {};
- };
代码如下;是想用base能base2赋值;能不能调动基类的拷贝构造?
- class Object
- {
- private:
- int value;
- public:
- Object(int x = 10) :value(x) { cout << "Create Object :" << this << endl; }
- ~Object() { cout << "Destroy Object :" << this << endl; }
- Object(const Object& obj) :value(obj.value) {
- cout << "Copy Create Object :" << this << endl;
- }
- };
- class Base :public Object {
- private:
- int num;
- public:
- Base(int x = 0) :num(x), Object(x + 10) { cout << "Create Base:" << this << endl; }
- ~Base() { cout << "Destroy Base: " << this << endl; }
- Base(const Base& base) :num(base.num) {
- cout << "Copy Creater Base :" << this << endl;
- }
- };
- int main() {
- Base base(10);
- Base bas2(base);
- return 0;
- }
所以并不会去调用基类的拷贝构造函数;也就是说拷贝构造函数不具有继承性;
原因是赋值兼容规则;上文有讲述; 4.7