在C++中,类的继承是一种重要的面向对象编程概念,它允许创建一个新类(称为派生类或子类),该类继承了另一个已存在的类(称为基类或父类)的属性和方法。通过继承,派生类可以重用基类的代码,并添加自己的特定功能。
C++中的类继承可以通过以下语法来实现:
class DerivedClass : accessSpecifier BaseClass {
// 派生类的成员和方法
};
其中:
DerivedClass
是派生类的名称;accessSpecifier
可以是public
、protected
或private
,用于指定派生类对基类成员的访问权限;BaseClass
是基类的名称,表示派生类从哪个类继承。
在类继承中,有以下几个关键概念:
-
公有继承(public inheritance):
- 使用
public
访问权限来继承基类。公有继承意味着基类的公有成员在派生类中仍然是公有的,保护成员在派生类中变为保护的,私有成员在派生类中不可访问。
- 使用
-
保护继承(protected inheritance):
- 使用
protected
访问权限来继承基类。保护继承意味着基类的公有和保护成员在派生类中都会变为保护的,私有成员在派生类中不可访问。
- 使用
-
私有继承(private inheritance):
- 使用
private
访问权限来继承基类。私有继承意味着基类的公有和保护成员在派生类中都会变为私有的,私有成员在派生类中不可访问。
- 使用
-
基类和派生类的关系:
- 派生类继承了基类的属性和方法,并可以添加自己的成员和方法。
- 派生类可以访问基类的公有和保护成员,但不能访问基类的私有成员。
- 派生类可以重写(override)基类的虚函数,实现多态性。
-
构造函数和析构函数的继承:
- 派生类可以继承基类的构造函数和析构函数。
- 在创建派生类对象时,会先调用基类的构造函数,再调用派生类的构造函数。
- 在销毁派生类对象时,会先调用派生类的析构函数,再调用基类的析构函数。
当我们考虑一个简单的图形类层次结构时,我们可以使用类的继承来展示这个概念。
假设我们有一个基类 Shape
,它表示各种形状的图形,然后我们创建两个派生类 Rectangle
和 Circle
,分别表示矩形和圆形。
下面是一个示例代码:
#include <iostream>
using namespace std;
// 基类:图形类
class Shape {
protected:
string color;
public:
Shape(string col);
void setColor(string col);
void displayColor();
};
Shape::Shape(string col) {
color = col;
}
void Shape::setColor(string col) {
color = col;
}
void Shape::displayColor() {
cout << "Color: " << color << endl;
}
// 派生类:矩形类
class Rectangle : public Shape {
private:
double length;
double width;
public:
Rectangle(double len, double wid, string col);
double getArea();
void display();
};
Rectangle::Rectangle(double len, double wid, string col) : Shape(col) {
length = len;
width = wid;
}
double Rectangle::getArea() {
return length * width;
}
void Rectangle::display() {
cout << "Length: " << length << endl;
cout << "Width: " << width << endl;
cout << "Area: " << getArea() << endl;
}
// 派生类:圆形类
class Circle : public Shape {
private:
double radius;
public:
Circle(double rad, string col);
double getArea();
void display();
};
Circle::Circle(double rad, string col) : Shape(col) {
radius = rad;
}
double Circle::getArea() {
return 3.14 * radius * radius;
}
void Circle::display() {
cout << "Radius: " << radius << endl;
cout << "Area: " << getArea() << endl;
}
int main() {
Rectangle rect(5.0, 3.0, "Blue");
Circle circle(2.5, "Red");
rect.displayColor();
rect.display();
circle.displayColor();
circle.display();
return 0;
}
在上述代码中,我们定义了一个基类 Shape
,它有一个 color
成员变量和一些操作颜色的方法。然后,我们创建了两个派生类 Rectangle
和 Circle
,它们分别继承了基类 Shape
。
在 Rectangle
类中,我们添加了 length
和 width
成员变量,并实现了计算面积和显示矩形信息的方法。而在 Circle
类中,我们添加了 radius
成员变量,并实现了计算面积和显示圆形信息的方法。
在 main
函数中,我们创建了一个矩形对象和一个圆形对象,并调用它们的成员函数来显示颜色和图形信息。
通过这个实例,我们可以看到基类 Shape
的属性和方法被派生类 Rectangle
和 Circle
继承,并且派生类可以添加自己的特定属性和方法。
多继承
多继承是指一个派生类可以从多个基类中继承属性和方法的能力。在C++中,可以使用多继承来创建一个派生类,它同时从多个基类中继承。
多继承的语法如下:
class DerivedClass : accessSpecifier BaseClass1, accessSpecifier BaseClass2, ... {
// 派生类的成员和方法
};
其中:
DerivedClass
是派生类的名称;accessSpecifier
可以是public
、protected
或private
,用于指定派生类对基类成员的访问权限;BaseClass1
,BaseClass2
, … 是基类的名称,表示派生类从哪些类继承。
多继承中,派生类会继承每个基类的属性和方法。派生类可以访问每个基类的公有成员,但不能访问私有成员。对于保护成员,其访问权限取决于使用的继承方式。
在多继承中,可能出现以下情况:
-
基类命名冲突:如果两个或多个基类具有相同的成员名称,派生类在使用该成员时必须明确指定基类的名称来消除歧义。
-
虚继承:当一个派生类从多个基类继承,并且这些基类之间存在继承关系时,可以使用虚继承来避免多次复制相同的基类子对象。通过使用虚继承,可以确保在派生类中只有一个共享的基类子对象。
-
菱形继承问题:当一个派生类从两个不同的基类继承,并且这两个基类又继承自同一个基类时,就会出现菱形继承问题。这可能导致在派生类中出现二义性,需要使用虚继承或明确指定基类的名称来解决。
为了说明多继承的概念,我们可以考虑一个简单的示例,假设我们有两个基类 Person
和 Employee
,然后我们创建一个派生类 Manager
,它同时从这两个基类中继承。
下面是一个示例代码:
#include <iostream>
using namespace std;
// 基类:人类
class Person {
protected:
string name;
public:
Person(string n);
void setName(string n);
void display();
};
Person::Person(string n) {
name = n;
}
void Person::setName(string n) {
name = n;
}
void Person::display() {
cout << "Name: " << name << endl;
}
// 基类:雇员类
class Employee {
protected:
int employeeId;
public:
Employee(int id);
void setEmployeeId(int id);
void display();
};
Employee::Employee(int id) {
employeeId = id;
}
void Employee::setEmployeeId(int id) {
employeeId = id;
}
void Employee::display() {
cout << "Employee ID: " << employeeId << endl;
}
// 派生类:经理类
class Manager : public Person, public Employee {
private:
string department;
public:
Manager(string n, int id, string dept);
void setDepartment(string dept);
void display();
};
Manager::Manager(string n, int id, string dept) : Person(n), Employee(id) {
department = dept;
}
void Manager::setDepartment(string dept) {
department = dept;
}
void Manager::display() {
Person::display();
Employee::display();
cout << "Department: " << department << endl;
}
int main() {
Manager manager("John Doe", 12345, "Sales");
manager.display();
return 0;
}
在上述代码中,我们定义了两个基类 Person
和 Employee
,它们分别表示人和雇员。然后,我们创建了一个派生类 Manager
,它同时从这两个基类中继承。
在 Manager
类中,我们添加了一个 department
成员变量,并实现了设置部门和显示信息的方法。通过使用多继承,Manager
类可以同时继承 Person
和 Employee
类的属性和方法。
在 main
函数中,我们创建了一个 Manager
对象,并调用它的 display
方法来显示经理的信息。通过多继承,Manager
类可以访问 Person
类和 Employee
类的成员函数,从而实现了对人名、员工ID和部门的显示。