[英]Why are virtual functions preferable over derived class objects?
所以我是学习虚拟函数的新手,我正在学习在线教程,但似乎无法找到我的问题的答案。 我想问一下为什么下面通过将基类对象设置为指向派生类对象来使用虚函数,而不是仅使用派生类对象本身来访问函数?
似乎无论哪种方式我都得到相同的输出,而且创建基类对象和虚拟函数似乎是额外的步骤。 我在一个在线教程上看到了一个类似的例子,它声称虚拟函数使编码更容易,但我不太明白这个例子的好处?
我在网上读到:
虚函数的主要优点是它们直接支持面向对象编程。 当您将函数声明为虚拟函数时,您是在说具体执行的代码取决于您调用它的对象的类型。
但是使用派生对象似乎已经是这种情况,并且不需要创建基类对象? 我确定我遗漏了一些明显的东西,所以我真的很感激任何帮助。 我展示了我在下面编写的示例代码,它类似于我在详述虚函数时所看到的:
#include <iostream>
using namespace std;
//////////////////////////////////////////////////////
//base class
class Shape {
public:
virtual void draw()=0; //pure virtual function
};
//derived classes
class Square : public Shape {
public:
void draw() {
cout << "Draw square" << endl;
}
};
class Circle : public Shape {
public:
void draw() {
cout << "Draw circle " << endl;
}
};
//////////////////////////////////////////////////////
int main()
{
Square so; //create derived class objects
Circle co;
Shape* shape1 = &so; //setting base class objects as pointers to derived objects
Shape* shape2 = &co;
shape1->draw(); //using base class objects to access derived class
shape2->draw();
so.draw(); //using derived class objects
co.draw();
}
使用基类指针类型和虚函数的巨大好处是,您可以拥有一个包含多种不同类型Shape
列表,并且您可以在一个函数中处理它们,因为它们将具有不同的行为它们的派生类型。
例如,我通过添加接受vector<Shapes*>&
的函数DrawAllShapes
修改了您的代码。 (小心使用原始指针。你真的应该在这里使用vector<std::unique_ptr<Shape>>&
或类似的东西。
这种模式具有难以置信的灵活性,它允许您在基类指针对象的集合上调用相同的函数,但会导致集合中每个对象根据其派生类型的不同行为。
#include <iostream>
#include <vector>
using namespace std;
//////////////////////////////////////////////////////
//base class
class Shape {
public:
virtual void draw() = 0; //pure virtual function
};
//derived classes
class Square : public Shape {
public:
void draw() {
cout << "Draw square" << endl;
}
};
class Circle : public Shape {
public:
void draw() {
cout << "Draw circle " << endl;
}
};
void DrawAllShapes(std::vector<Shape*>& shapes) {
for (int i = 0; i < shapes.size(); ++i) {
shapes[i]->draw();
}
}
//////////////////////////////////////////////////////
int main()
{
std::vector<Shape*> shapeVec{ new Square, new Circle, new Square, new Square, new Circle };
DrawAllShapes(shapeVec);
system("pause");
}
另外,想象一下,如果您正在使用一个已经定义了 Shape 类和多个形状的预构建图形库。 如果您想添加自己的新型 Shape 并使其与库的所有功能完美配合,该怎么办? 您所要做的就是创建您自己的派生类并实现库的 Shape 类公开的所有必要的虚函数,然后您实际上已经扩展了库超出了其原始功能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.