为什么虚函数优于派生 class 对象?
Why are virtual functions preferable over derived class objects?
所以我刚开始学习虚函数,我正在学习在线教程,但我似乎找不到问题的答案。我想问一下为什么通过将基础 class 对象设置为指向派生 class 对象来使用下面的虚函数比仅使用派生 class 对象本身来访问函数更可取?
似乎我得到了相同的输出,而且创建基础 class 对象和虚函数似乎是额外的步骤。我在一个在线教程中看到了一个与此类似的示例,该教程声称虚函数使编码更容易,但我不太清楚这个示例的好处?
我在网上看到:
The main advantage of virtual functions are that they directly support object oriented programming. When you declare a function as virtual you're saying that exactly what code is executed depends on the type of the object you call it against.
但使用派生对象似乎已经是这种情况,并且创建基础 class 对象是不必要的?我确定我遗漏了一些明显的东西,所以我非常感谢任何帮助。我在下面展示了我编写的示例代码,它与我在详细介绍虚函数时看到的代码类似:
#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();
}
使用基本 class 指针类型和虚函数的巨大好处是您可以拥有一个包含多种不同类型 Shape
的列表,并且您可以处理它们在单个函数中,由于派生类型不同,它们都将具有不同的行为。
例如,我修改了您的代码,添加了接受 vector<Shapes*>&
的函数 DrawAllShapes
。 (小心使用原始指针。你真的应该在这里使用 vector<std::unique_ptr<Shape>>&
或类似的东西。
这种模式具有令人难以置信的灵活性,它允许您在基础 class 指针对象的集合上调用相同的函数,但会根据其派生类型为集合中的每个对象产生不同的行为。
#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");
}
另外,想象一下如果您使用的是一个预建的图形库,它已经定义了一个形状 class 和多个形状。如果您想添加自己的新型 Shape 并使其与库的所有函数完美配合怎么办?您所要做的就是创建您自己的派生 class 并实现库的 Shape class 公开的所有必要虚函数,然后您实际上已经扩展了库的原始功能。
所以我刚开始学习虚函数,我正在学习在线教程,但我似乎找不到问题的答案。我想问一下为什么通过将基础 class 对象设置为指向派生 class 对象来使用下面的虚函数比仅使用派生 class 对象本身来访问函数更可取?
似乎我得到了相同的输出,而且创建基础 class 对象和虚函数似乎是额外的步骤。我在一个在线教程中看到了一个与此类似的示例,该教程声称虚函数使编码更容易,但我不太清楚这个示例的好处?
我在网上看到:
The main advantage of virtual functions are that they directly support object oriented programming. When you declare a function as virtual you're saying that exactly what code is executed depends on the type of the object you call it against.
但使用派生对象似乎已经是这种情况,并且创建基础 class 对象是不必要的?我确定我遗漏了一些明显的东西,所以我非常感谢任何帮助。我在下面展示了我编写的示例代码,它与我在详细介绍虚函数时看到的代码类似:
#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();
}
使用基本 class 指针类型和虚函数的巨大好处是您可以拥有一个包含多种不同类型 Shape
的列表,并且您可以处理它们在单个函数中,由于派生类型不同,它们都将具有不同的行为。
例如,我修改了您的代码,添加了接受 vector<Shapes*>&
的函数 DrawAllShapes
。 (小心使用原始指针。你真的应该在这里使用 vector<std::unique_ptr<Shape>>&
或类似的东西。
这种模式具有令人难以置信的灵活性,它允许您在基础 class 指针对象的集合上调用相同的函数,但会根据其派生类型为集合中的每个对象产生不同的行为。
#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");
}
另外,想象一下如果您使用的是一个预建的图形库,它已经定义了一个形状 class 和多个形状。如果您想添加自己的新型 Shape 并使其与库的所有函数完美配合怎么办?您所要做的就是创建您自己的派生 class 并实现库的 Shape class 公开的所有必要虚函数,然后您实际上已经扩展了库的原始功能。