IT评测·应用市场-qidao123.com

标题: C++中的继承 [打印本页]

作者: 熊熊出没    时间: 2024-7-14 14:17
标题: C++中的继承
一、继承的概念和定义

1.1 继承的概念

继承(inheritance)机制是面向对象程序设计是代码可以复用的最重要的手段,它答应程序员在保持原有类特性的基础上举行扩展,增长功能,如许产生新的类,称为派生类。继承出现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们打仗的复用都是函数复用,继承是类设计层次的复用
下面是一个继承的实例:
  1. #include<iostream>
  2. #include<vector>
  3. using namespace std;
  4. class Person
  5. {
  6. public:
  7.         void Print()
  8.         {
  9.                 cout << "name:" << _name << endl;
  10.                 cout << "age:" << _age << endl;
  11.         }
  12. protected:
  13.         string _name = "son";
  14.         int _age = 18;
  15. };
  16. //继承父类Person
  17. class Student : public Person
  18. {
  19. protected:
  20.         int _stuid;//学号
  21. };
  22. class Teacher : public Person
  23. {
  24. protected:
  25.         int _jobid;//工号
  26. };
  27. int main()
  28. {
  29.         Person p;
  30.         Student s;
  31.         Teacher t;
  32.         t.Print();
  33.         return 0;
  34. }
复制代码
继承后父类Person的成员(成员函数+成员变量)都会成为子类的一部分,但是是一种类似拷贝的方式但又不是拷贝,改变子类中继承父类的成员,真正的父类对象中的成员不会改变。

1.2 继承的定义

1.2.1 定义格式

  1. class Student : public Person
  2. {
  3. protected:
  4.         int _stuid;//学号
  5. };
复制代码
上面的形式就是继承的定义格式 :次序是 class 子类(派生类) : 继承方式(访问限定符) 父类
上面的Person是父类也叫做基类。Student是子类,也称作派生类
留意:继承父类的成员变量相当于拷贝过来的,继承父类的函数是共用的一个的
父类和子类的构造函数是各自的,不是共用的,但子类可以使用父类的构造来处置处罚子类中父类的成员
1.2.2 继承关系和访问限定符



###1.2.3 继承基类成员访问方式的变化
类成员/继承方式public继承protected继承private继承基类的public成员派生类的public成员派生类的的protected成员派生类的private成员基类的protected成员派生类的protected成员派生类的protected成员派生类的private成员基类的private成员在派生类中不可见在派生类中不可见在派生类中不可见 二、基类和派生类对象赋值转换


效果图如下:

下面是我们的代码实例:
  1. class Person
  2. {
  3. protected:
  4.         string _name;
  5.         string _sex;
  6.         int _age;
  7. };
  8. //继承父类Person
  9. class Student : public Person
  10. {
  11. public:
  12.         int _no;
  13. };
  14. void test()
  15. {
  16.         Student s;
  17.         //子类对象可以给父类对象赋值
  18.         Person per = s;
  19.         Person* pper = &s;
  20.         Person& rper = s;
  21.         //父类对象不能给子类对象赋值
  22.         //s = per;
  23. }
复制代码
三、 继承中的作用域

实例1(成员变量之间构成隐藏):
  1. class Person
  2. {
  3. protected:
  4.         string _name = "son";
  5.         int _id = 111;
  6. };
  7. class Student : public Person
  8. {
  9. public:
  10.         void Print()
  11.         {
  12.                 cout << "name: " << _name << endl;
  13.                 cout << "id: " << Person::_id << endl;
  14.                 cout << "id: " << _id << endl;
  15.         }
  16. protected:
  17.         int _id = 999;
  18. };
  19. void test2()
  20. {
  21.         Student s1;
  22.         s1.Print();
  23. }
复制代码
实例2(成员函数之间构成隐藏):
  1. class A
  2. {
  3. public:
  4.         void fun()
  5.         {
  6.                 cout << "fun()" << endl;
  7.         }
  8. };
  9. class B : public A
  10. {
  11. public:
  12.         void fun(int i)
  13.         {
  14.                 cout << "fun(int i)" << i << endl;
  15.         }
  16. };
  17. void test3()
  18. {
  19.         B b;
  20.         b.fun(109);
  21. }
复制代码
实例2中的fun()和fun(int i) 之间是不构成重载的因为它们不在同一作用域,B中的fun和A中的fun构成隐藏,成员函数只要满意函数名相同就构成隐藏。
四、派生类中的默认成员函数

留意:
五、 继承与友元

友元关系是不能继承的,也就是说基类友元不能访问子类私有和保护成员。即基类的友元其派生类不是友元。
代码实例:
  1. #include<iostream>
  2. using namespace std;
  3. class Student;
  4. class Person
  5. {
  6. public:
  7.     friend void Display(const Person& p, const Student& s);
  8. protected:
  9.         string _name;
  10. };
  11. class Student : public Person
  12. {
  13. protected:
  14.         int _stunum; // 学号
  15. };
  16. void Display(const Person& p, const Student& s)
  17. {
  18.         cout << p._name << endl;
  19.         cout << s._stunum << endl;
  20. }
  21. int main()
  22. {
  23.         Person p1;
  24.         Student s1;
  25.         Display(p1, s1);
  26.         return 0;
  27. }
复制代码
六、 继承与静态成员

基类定义了static静态成员后,整个继承体系中就只有一个如许的成员,也就是无论派生出多少个子类都只有一个static成员实例。
  1. class Person
  2. {
  3. public:
  4.     Person()
  5.     {
  6.         ++_count;
  7.     }
  8. protected:
  9.     string _name; // 姓名
  10. public:
  11.     static int _count; // 统计人数
  12. };
  13. int Person::_count = 0;
  14. class Student : public Person
  15. {
  16. protected:
  17.     int _stunum; // 学号
  18. };
  19. class Graduate : public Student
  20. {
  21. protected:
  22.     string _seminarcourse; // 研究项目
  23. };
  24. void TestPerson()
  25. {
  26.     Student s1;
  27.     Student s2;
  28.     Student s3;
  29.     Graduate s4;
  30.     cout << "人数: " << Person::_count << endl;
  31.     Student::_count = 0;
  32.     cout << "人数 :" << Person::_count << endl;
  33. }
复制代码
七、 复杂的菱形继承以及菱形虚拟继承

单继承:一个子类只有一个直接父类时的关系就是单继承。

多继承:一个子类有两个或者两个以上的直接父类时的关系就是多继承。

菱形继承:菱形继承是多继承的一种特殊情况。

菱形继承存在的问题:菱形继承有数据冗余和二义性的问题,在Assistant的对象中Person成员会有两份。

下面是代码实例:
  1. class Person
  2. {
  3. public:
  4.     string _name; //姓名
  5. };
  6. class Student : public Person
  7. {
  8. protected:
  9.     int _num; //学号
  10. };
  11. class Teacher : public Person
  12. {
  13.     int _id; //编号
  14. };
  15. //继承上面两个类
  16. class Assistant : public Student, public Teacher
  17. {
  18. protected:
  19.     string _majorCourse; //主修课程
  20. };
  21. void Test()
  22. {
  23.     Assistant a;
  24.     //这样会有二义性无法确定访问的是哪一个
  25.     a._name = "rebenn";
  26.     //可以显示的指定访问那个父类的成员来解决二义性问题,但是无法解决数据冗余的问题
  27.     a.Student::_name = "peter";
  28.     a.Teacher::_name = "woter";
  29. }
复制代码
虚拟继承可以解决菱形继承的二义性以及数据冗余的问题, 就像上面的继承关系,在Student和Teacher的继承Person时使用虚拟继承,即可解决二义性和数据冗余的问题。留意虚拟继承不要在其他地方去随意使用。
虚拟继承方式:
   class 类名 :virtual public 父类
  virtual是虚拟继承的关键字。
代码实例:
  1. class Person
  2. {
  3. public:
  4.     string _name; // 姓名
  5. };
  6. class Student : virtual public Person
  7. {
  8. protected:
  9.     int _num; //学号
  10. };
  11. class Teacher : virtual public Person
  12. {
  13. protected:
  14.     int _id; //工号
  15. };
  16. class Assistant : public Student, public Teacher
  17. {
  18. protected:
  19.     string _majorcourse; //主修课程
  20. };
  21. void test()
  22. {
  23.     Assistant a;
  24.     a._name = "rebenn";
  25. }
复制代码
留意:实践中,不发起使用菱形继承,可以使用多继承,但也要少用。
io流就是一个菱形继承, 菱形继承是特殊的多继承。
八、 继承和组合


代码实例:
  1. //Car和BWM, Car和Benz之间是is-a关系,继承
  2. class Car
  3. {
  4. protected:
  5.     string _colour = "黑色"; //颜色
  6.     string _num = "xxxxxx";//车牌号
  7. };
  8. class BMW : public Car
  9. {
  10. public:
  11.     void Drive()
  12.     {
  13.         cout << "好操作" << endl;
  14.     }
  15. };
  16. class Benz : public Car
  17. {
  18. public:
  19.     void Drive()
  20.     {
  21.         cout << "车座舒适" << endl;
  22.     }
  23. };
  24. //Tire和Car构成has-a的关系, 组合
  25. class Tire
  26. {
  27. protected:
  28.     string _brand = "xxxx"; //品牌
  29.     size_t _size = 18; //尺寸
  30. };
  31. class Car
  32. {
  33. protected:
  34.     string _colour = "xxx"; //颜色
  35.     string _num = "xxxxx"; //车牌号
  36.     Tire _t; //轮胎
  37. };
复制代码
class BMW : public Car
{
public:
void Drive()
{
cout << “好操作” << endl;
}
};
class Benz : public Car
{
public:
void Drive()
{
cout << “车座舒适” << endl;
}
};
//Tire和Car构成has-a的关系, 组合
class Tire
{
protected:
string _brand = “xxxx”; //品牌
size_t _size = 18; //尺寸
};
class Car
{
protected:
string _colour = “xxx”; //颜色
string _num = “xxxxx”; //车牌号
Tire _t; //轮胎
};
[code][/code]
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4