引言
在C++中,多态、继承和封装是面向对象编程(OOP)的三大核心特性。它们共同支持了代码的复用、扩展和维护。本文将深入解析这三个特性的原理,并通过示例展示它们在C++中的应用。
封装(Encapsulation)
原理
封装是一种将数据和操作数据的函数绑定在一起,形成一个不可分割的整体(即类)的技术。它隐藏了对象的内部实现细节,仅对外公开接口(public成员函数),从而提高了数据的安全性,并简化了对象的使用。
示例
cpp
#include <iostream>
using namespace std;
class Account {
private:
double balance;
public:
Account(double initialBalance) : balance(initialBalance) {}
void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
double getBalance() const {
return balance;
}
};
int main() {
Account myAccount(100.0);
myAccount.deposit(50.0);
cout << "Balance: " << myAccount.getBalance() << endl;
return 0;
}
继承(Inheritance)
原理
继承允许我们定义一个基于现有类的类(称为子类或派生类),从而复用和扩展现有类的功能。子类可以继承父类的属性和方法,也可以添加新的属性和方法或重写(Override)继承的方法。
示例
cpp
#include <iostream>
using namespace std;
class Vehicle {
protected:
string brand;
public:
Vehicle(string b) : brand(b) {}
virtual void display() const {
cout << "Brand: " << brand << endl;
}
};
class Car : public Vehicle {
private:
int seats;
public:
Car(string b, int s) : Vehicle(b), seats(s) {}
void display() const override {
Vehicle::display(); // 调用父类方法
cout << "Seats: " << seats << endl;
}
};
int main() {
Car myCar("Toyota", 5);
myCar.display();
return 0;
}
多态(Polymorphism)
原理
多态允许不同类的对象对同一消息作出响应。在C++中,多态通常通过虚函数实现。当通过基类指针或引用来调用虚函数时,会根据指针或引用实际指向的对象的类型来调用相应的函数版本,这就是运行时多态(也称为动态多态)。
示例
cpp
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class Shape {
public:
virtual void draw() const = 0; // 纯虚函数,强制子类实现
virtual ~Shape() {} // 虚析构函数
};
class Circle : public Shape {
public:
void draw() const override {
cout << "Drawing Circle" << endl;
}
};
class Rectangle : public Shape {
public:
void draw() const override {
cout << "Drawing Rectangle" << endl;
}
};
int main() {
vector<shared_ptr<Shape>> shapes;
shapes.push_back(make_shared<Circle>());
shapes.push_back(make_shared<Rectangle>());
for (const auto& shape : shapes) {
shape->draw(); // 运行时多态
}
return 0;
}
综合示例
下面将提供一个基于C++的综合示例代码,该代码结合了多态、继承和封装的概念,以创建一个简单的绘图系统。在这个系统中,我们将定义几个图形类(如圆形和矩形),它们都继承自一个共同的基类Shape,并实现了自己的draw方法。最后,我们将通过一个主函数来展示如何使用这些图形类,并利用多态性统一处理不同的图形对象。
代码
cpp
#include <iostream>
#include <vector>
#include <memory>
// 基类Shape,包含纯虚函数draw()
class Shape {
public:
virtual void draw() const = 0; // 纯虚函数,强制派生类实现
virtual ~Shape() {} // 虚析构函数,确保通过基类指针删除派生类对象时调用正确的析构函数
};
// 圆形类,继承自Shape
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
void draw() const override {
std::cout << "Drawing Circle with radius: " << radius << std::endl;
}
};
// 矩形类,继承自Shape
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {}
void draw() const override {
std::cout << "Drawing Rectangle with width: " << width << " and height: " << height << std::endl;
}
};
// 主函数,展示如何使用多态和继承
int main() {
// 使用智能指针存储Shape类型的对象,这些对象可以是Circle或Rectangle的实例
std::vector<std::shared_ptr<Shape>> shapes;
shapes.push_back(std::make_shared<Circle>(5.0));
shapes.push_back(std::make_shared<Rectangle>(3.0, 4.0));
// 通过基类指针调用draw方法,展示多态性
for (const auto& shape : shapes) {
shape->draw();
}
return 0;
}
代码详解
代码中:
基类Shape:定义了一个纯虚函数draw(),这要求所有从Shape派生的类都必须实现draw()方法。同时,提供了一个虚析构函数,这是处理通过基类指针删除派生类对象时的一个好习惯,可以确保正确的析构函数被调用。
派生类Circle和Rectangle:这两个类都继承自Shape类,并实现了自己的draw()方法。在Circle类中,draw()方法输出圆的半径;在Rectangle类中,draw()方法输出矩形的宽度和高度。
主函数main:首先,创建了一个std::vector<std::shared_ptr>类型的容器,用于存储指向Shape对象的智能指针。然后,向该容器中添加了两个对象:一个Circle对象和一个Rectangle对象。由于这两个类都继承自Shape,因此它们都可以被存储在同一容器中。最后,通过遍历容器并使用基类指针调用draw()方法,展示了多态性。尽管我们使用的是Shape类型的指针,但实际上调用的是指向对象的实际类型(Circle或Rectangle)的draw()方法。
这个示例展示了多态、继承和封装在C++中的实际应用,以及它们如何共同工作以创建灵活且可扩展的面向对象程序。