1.纯虚函数与抽象类的一个例子
#include <iostream>
class Shape {
public:
virtual void draw() const = 0; // 纯虚函数
//virtual void draw() = 0;
virtual ~Shape() {} // 虚析构函数
};
class Circle : public Shape {
private:
float radius;
public:
Circle(float r) : radius(r) {}
void draw() const override {
std::cout << "Drawing a circle with radius " << radius << std::endl;
}
};
class Rectangle : public Shape {
private:
float width;
float height;
public:
Rectangle(float w, float h) : width(w), height(h) {}
void draw() const override {
std::cout << "Drawing a rectangle with width " << width << " and height " << height << std::endl;
}
};
int main() {
// Shape s; // 错误,不能实例化抽象类
Circle c(5.0);
Rectangle r(3.0, 4.0);
//Shape* shapes[] = { &c, &r };
//for (const auto& shape : shapes) {
// shape->draw(); // 多态性,调用正确对象的draw方法
//}
//使用抽象类(基类)的指针或引用
Shape* shape_cptr = &c;
Shape* shape_rptr = &r;
shape_cptr->draw();
shape_rptr->draw();
//使用实例化Circle对象的指针
Circle* circle_ptr = &c;
circle_ptr->draw();
//使用实例化Circle对象本身进行访问
Rectangle myrectangle(3.0, 4.6);
myrectangle.draw();
return 0;
}
2.为什么习惯使用基类的指针或引用?
为什么在有关纯虚函数与抽象类,以及实现动态多态时,常常使用基类的指针或引用来访问派生类的成员是一种常见的做法。
答:
在面向对象编程中,使用基类的指针或引用来访问派生类的成员是一种常见的做法,尤其是在实现多态性时。多态性允许不同类型的对象通过共同的接口(通常是基类的接口)进行交互,这样可以编写更通用、更灵活的代码。
使用基类指针或引用的好处包括:
- 代码的通用性:你可以编写处理基类指针或引用的代码,这些代码可以与任何派生类对象一起工作,而不需要知道具体的派生类类型。
- 接口的稳定性:基类定义了一个稳定的接口,即使派生类发生变化,使用基类指针或引用的代码也不需要改变。
- 容器管理:可以使用基类指针的容器(如
std::vector或std::list)来存储不同类型的派生类对象,这样容器中的元素就可以是多态的。 - 运行时绑定:使用指针或引用可以实现运行时多态,这意味着在运行时根据对象的实际类型来调用相应的成员函数。
在你的代码中,你确实可以直接使用派生类的对象来调用成员函数,如:
Rectangle myrectangle(3.0, 4.6);
myrectangle.draw();
这种方法在你知道对象的具体类型时是完全有效的。然而,如果你想要编写可以处理多种形状类型的代码,使用基类指针或引用会更加灵活。例如,如果你有一个函数,它需要能够绘制任何类型的形状,你可以这样写:
void drawShape(const Shape& shape) {
shape.draw(); // 多态性,调用正确对象的draw方法
}
int main() {
Circle c(5.0);
Rectangle r(3.0, 4.0);
drawShape(c); // 传递Circle对象
drawShape(r); // 传递Rectangle对象
return 0;
}
这样,无论传入的是 Circle 还是 Rectangle 对象,drawShape 函数都能正确地调用相应的 draw 方法。这就是多态性的强大之处,它允许你编写更通用的代码来处理不同的对象类型。

被折叠的 条评论
为什么被折叠?



