一、C++ 中多态性在实际项目中的应用场景
(一)图形绘制系统
背景和需求
在图形绘制软件中,可能需要绘制多种不同的图形,如圆形、矩形、三角形等。每个图形都有自己的绘制方法,但是在处理图形集合进行绘制操作时,希望能够以统一的方式来调用它们的绘制函数。
多态的实现方式和优势
可以定义一个基类Shape,其中有一个纯虚函数draw()。然后让Circle、Rectangle、Triangle等类都继承自Shape并实现自己的draw()函数。
例如:
class Shape {
public:
virtual void draw() = 0;
};
class Circle : public Shape {
public:
void draw() override {
// 绘制圆形的具体代码
}
};
class Rectangle : public Shape {
public:
void draw() override {
// 绘制矩形的具体代码
}
};
当有一个vector<Shape*>存储各种图形的指针时,可以通过循环调用每个图形对象的draw()函数,而不需要为每种图形单独编写绘制代码。这样的代码结构更易于维护和扩展。例如:
int main() {
std::vector<Shape*> shapes;
shapes.push_back(new Circle());
shapes.push_back(new Rectangle());
for (Shape* shape : shapes) {
shape->draw();
}
return 0;
}
(二)游戏开发中的角色行为
背景和需求
在游戏中,不同的角色(如战士、法师、刺客等)有不同的行为,如攻击、移动、使用技能等。但游戏引擎在处理角色行为更新时,希望能够以统一的方式调用这些行为函数。
多态的实现方式和优势
可以定义一个基类Character,其中有虚函数attack()、move()等。然后不同的角色类继承自Character并实现自己的行为函数。
例如:
class Character {
public:
virtual void attack() = 0;
virtual void move() = 0;
};
class Warrior : public Character {
public:
void attack() override {
// 战士攻击的具体代码
}
void move() override {
// 战士移动的具体代码
}
};
class Mage : public Character {
public:
void attack() override {
// 法师攻击的具体代码
}
void move() override {
// 法师移动的具体代码
}
};
游戏引擎可以通过一个Character指针数组或容器来管理游戏中的所有角色,在游戏循环中统一调用它们的行为函数,方便更新角色状态,提高代码的复用性和可扩展性。
二、C++ 中面向对象编程实现数据隐藏
访问控制修饰符的使用
C++ 中有三种访问控制修饰符:public、private和protected。
private成员变量和函数:将类的成员变量和函数声明为private,可以限制它们只能在类的内部被访问。例如:
class MyClass {
private:
int privateVariable;
void privateFunction() {
// 这个函数只能在类内部访问
}
public:
MyClass() {
privateVariable = 0;
privateFunction();
}
};
这样,外部代码无法直接访问privateVariable和privateFunction,只能通过类提供的public接口来间接操作或获取相关信息。
protected访问控制
protected成员对于类的外部是不可访问的,但是可以在派生类中访问。这在继承关系中很有用,它允许派生类继承基类的一些内部实现细节,但仍然限制外部对这些细节的访问。
例如:
class Base {
protected:
int protectedVariable;
public:
Base() {
protectedVariable = 1;
}
};
class Derived : public Base {
public:
void accessProtected() {
// 可以在派生类中访问基类的protected成员
std::cout << protectedVariable << std::endl;
}
};
通过接口(public函数)访问数据
类通常会提供public函数来访问和修改private或protected的数据成员。这些public函数可以对数据进行合法性检查等操作,保证数据的完整性。
例如:
class DataHolder {
private:
int data;
public:
int getData() const {
return data;
}
void setData(int newData) {
if (newData > 0) {
data = newData;
}
}
};
这样,外部代码只能通过getData和setData函数来访问和修改data,而不能直接操作data,从而实现了数据隐藏和数据安全性。