面试题答案
一键面试-
定义基类:
class Shape { public: virtual void draw() const = 0; };
这里定义了一个抽象基类
Shape
,其中包含一个纯虚函数draw()
。纯虚函数使得Shape
类成为抽象类,不能被实例化,其目的是为所有具体的图形类提供一个统一的接口。 -
定义具体图形类:
- 圆形:
class Circle : public Shape { public: void draw() const override { std::cout << "Drawing a circle." << std::endl; } };
- 矩形:
class Rectangle : public Shape { public: void draw() const override { std::cout << "Drawing a rectangle." << std::endl; } };
- 三角形:
class Triangle : public Shape { public: void draw() const override { std::cout << "Drawing a triangle." << std::endl; } };
这些具体的图形类都继承自
Shape
类,并实现了draw()
函数。override
关键字用于显式表明该函数是重写基类的虚函数,增加代码的可读性和可维护性。 -
使用多态:
#include <iostream> #include <vector> int main() { std::vector<Shape*> shapes; shapes.push_back(new Circle()); shapes.push_back(new Rectangle()); shapes.push_back(new Triangle()); for (const auto& shape : shapes) { shape->draw(); } for (const auto& shape : shapes) { delete shape; } return 0; }
在
main
函数中,创建了一个Shape
指针的向量。将不同具体图形类的对象指针加入到这个向量中。通过遍历这个向量,调用draw()
函数,根据指针实际指向的对象类型,调用相应图形类的draw()
函数,这就是多态的体现。 -
多态如何让添加新图形变得容易:
- 代码修改量小:若要添加新图形,比如
Square
。只需定义一个新的类Square
继承自Shape
类,并实现draw()
函数。
class Square : public Shape { public: void draw() const override { std::cout << "Drawing a square." << std::endl; } };
- 不影响现有代码:在
main
函数中,只需像添加其他图形一样,将Square
对象的指针加入到shapes
向量中,而无需修改现有图形类的代码和draw()
函数调用的逻辑。
int main() { std::vector<Shape*> shapes; shapes.push_back(new Circle()); shapes.push_back(new Rectangle()); shapes.push_back(new Triangle()); shapes.push_back(new Square()); for (const auto& shape : shapes) { shape->draw(); } for (const auto& shape : shapes) { delete shape; } return 0; }
这样,通过多态,添加新图形变得简单且不会对现有代码造成较大影响,提高了代码的扩展性。
- 代码修改量小:若要添加新图形,比如
上述代码使用了动态内存分配,在实际应用中可以考虑使用智能指针来管理内存,以避免内存泄漏。例如:
#include <iostream>
#include <vector>
#include <memory>
class Shape {
public:
virtual void draw() const = 0;
};
class Circle : public Shape {
public:
void draw() const override {
std::cout << "Drawing a circle." << std::endl;
}
};
class Rectangle : public Shape {
public:
void draw() const override {
std::cout << "Drawing a rectangle." << std::endl;
}
};
class Triangle : public Shape {
public:
void draw() const override {
std::cout << "Drawing a triangle." << std::endl;
}
};
class Square : public Shape {
public:
void draw() const override {
std::cout << "Drawing a square." << std::endl;
}
};
int main() {
std::vector<std::unique_ptr<Shape>> shapes;
shapes.emplace_back(std::make_unique<Circle>());
shapes.emplace_back(std::make_unique<Rectangle>());
shapes.emplace_back(std::make_unique<Triangle>());
shapes.emplace_back(std::make_unique<Square>());
for (const auto& shape : shapes) {
shape->draw();
}
return 0;
}
这样使用智能指针 std::unique_ptr
可以自动管理对象的生命周期,避免手动释放内存可能带来的错误。