
本文共 4277 字,大约阅读时间需要 14 分钟。
C++继承概念详解
继承是C++中一个强大的功能,它允许我们在定义子类时重复利用父类的属性和方法,从而避免代码冗余。本文将详细介绍C++继承的概念、应用场景、继承格式以及相关的实现细节。
一、继承的概念
在现实世界中,许多对象之间存在整体与部分的关系。例如,Student("学生")和Teacher("老师")都可以看作是Person("人")的子类。Person类包含了姓名、年龄和性别等通用属性,而Student和Teacher类则在这些基础上分别增加了学号和工号的属性。这种继承关系使得代码实现更加高效和可维护。
二、继承的具体操作
1.1 代码冗余问题 不使用继承时,我们需要在Student和Teacher类中分别定义姓名、年龄和性别等属性,这会导致冗余代码。例如:
class Person { public: Person(string name = "Tom", int age = 20, int sex = 1) : _name(name), _age(age), _sex(sex) { } string _name; int _age; int _sex; };
class Student { public: Student(string name, int age, int sex, int stuNum) : _name(name), _age(age), _sex(sex), _stuNum(stuNum) { } string _name; int _age; int _sex; int _stuNum; };
class Teacher { public: Teacher(string name, int age, int sex, int workNum) : _name(name), _age(age), _sex(sex), _workNum(workNum) { } string _name; int _age; int _sex; int _workNum; };
2.2 继承后代码优化 通过引入继承,我们可以避免代码冗余。例如:
class Person { public: Person(string name = "Tom", int age = 20, int sex = 1) : _name(name), _age(age), _sex(sex) { } string _name; int _age; int _sex; };
class Student : public Person { public: Student(int stuNum) : _stuNum(stuNum) { } private: int _stuNum; };
class Teacher : public Person { public: Teacher(int workNum) : _workNum(workNum) { } private: int _workNum; };
这种继承方式使得Student和Teacher类都继承了Person类的属性,从而实现了代码的精简。
三、继承格式
在C++中,继承格式的书写方式如下:
class DerivedClass : public BaseClass { // 继承自BaseClass的内容 };
其中:
需要注意的是,protected成员在继承时的访问权限不会改变。例如:
class Person { public: Person(string name = "Tom", int age = 20, int sex = 1) : _name(name), _age(age), _sex(sex) { } private: protected: string _name; int _age; int _sex; };
class Student : public Person { public: Student(int stuNum) : _stuNum(stuNum) { } private: int _stuNum; };
在这种情况下,Person类的_name、_age和_sex属性会被Student类继承为protected类型。
四、成员的继承与访问
class Person { private: string _name; int _age; int _sex; };
class Student : public Person { public: Student(int stuNum) : _stuNum(stuNum) { } private: int _stuNum; };
在这种情况下,Student类的_name、_age和_sex属性虽然存在,但由于它们是private类型,无法在Student类中直接访问。
- public和protected成员的继承 父类中定义为public或protected的成员在子类中也保持相同的访问级别。例如:
- 友元函数的继承 友元函数不能被继承,因为友元关系不属于类的成员关系。例如:
- 静态成员的继承 静态成员可以被继承,但静态成员不会为每个对象单独分配空间。例如:
- 菱形继承问题 菱形继承(多个继承关系)可能导致数据冗余和二义性。例如:
- 虚拟继承的解决方案 为了解决菱形继承带来的问题,C++引入了虚拟继承(virtual inheritance)。虚拟继承通过在基类中定义virtual关键字来避免多个继承关系导致的数据冗余和二义性。例如:
class Person { public: string _name; int _age; int _sex; };
class Student : public Person { public: Student(int stuNum) : _stuNum(stuNum) { } private: int _stuNum; };
在这种情况下,Student类的_name、_age和_sex属性可以通过public或protected方式访问。
五、友元与静态成员的继承
class Person { public: friend class Student; Person(string name = "Tom", int age = 20, int sex = 1) : _name(name), _age(age), _sex(sex) { } string _name; int _age; int _sex; };
class Student : public Person { public: Student(int stuNum) : _stuNum(stuNum) { } private: int _stuNum; };
class Person { public: static const int MAX_AGE = 100; };
class Student : public Person { public: Student(int stuNum) : _stuNum(stuNum) { } private: int _stuNum; };
在这种情况下,Student类继承了Person类的MAX_AGE静态成员,但MAX_AGE只会在类级别存在一个实例。
六、菱形继承与虚拟继承
class Person { public: string _name; int _age; int _sex; };
class Student : public Person { public: int _stuNum; };
class Teacher : public Person { public: int _workNum; };
class Assistant : public Student, public Teacher { public: int _d; };
在这种情况下,Assistant类继承了Student和Teacher类的属性,导致_name和_age在两个类中各存储一次,导致数据冗余。
class Person { public: virtual ~Person() {} string _name; int _age; int _sex; };
class Student : virtual public Person { public: int _stuNum; };
class Teacher : virtual public Person { public: int _workNum; };
class Assistant : public Student, public Teacher { public: int _d; };
在这种情况下,Assistant类继承了Student和Teacher类的属性,但虚拟继承确保了只存储一次Person类的属性,从而解决了数据冗余问题。
七、虚拟继承的实现原理 虚拟继承通过在基类中定义虚拟符号来实现,确保每个继承链只存储一次基类的成员。例如:
class A { public: virtual ~A() {} int _a; };
class B : virtual public A { public: int _b; };
class C : virtual public A { public: int _c; };
class D : public B, public C { public: int _d; };
在这种情况下,D类的虚拟继承确保了_A类的属性只存储一次,而B和C类的继承关系不会导致重复存储。
通过上述内容可以看到,C++的继承机制提供了强大的代码复用能力,同时也需要注意继承方式的选择和虚拟继承的使用,以避免潜在的问题。