从超类指针向量调用重写方法

Calling overridden methods from a vector of superclass pointers

我目前正在使用 C++ 在 OpenGL 中编写一个小游戏。来自 non-C++ 背景,我有一个关于覆盖方法以及如何使用 superclass 类型的指针调用它们的简单问题。

情况是这样的:我有一个 class Polygon 包含方法 void draw()。这个 class 有两个 children,分别称为 RectangleCircle,它们都覆盖了绘制方法,因为我根据绘制的多边形类型使用不同的 OpenGL 调用。

现在考虑一下:我希望将所有多边形(包括矩形和圆形)存储在 std::vector<Polygon*> 中。这很好。但是,遍历向量并调用 draw 会自动求助于该方法的 superclass' 版本。

如何创建一个 superclass-pointer 类型的向量,在其中存储指向子 class object 的指针,并根据 [=] 的实际类型调用重写的函数29=] 正在使用?

您描述的是多态性(或您当前的实现中缺少多态性)。

要使您的 draw 函数具有多态性,您必须声明它 virtual。请参阅下面的示例:

class Polygon {
public:
    virtual ~Polygon() {}
    virtual void draw() = 0;
};

class Rectangle : public Polygon
{
public:
    void draw() override { std::cout << "Rectangle::draw()\n"; }
};

class Circle : public Polygon
{
public:
    void draw() override { std::cout << "Circle::draw()\n"; }
};

注意以上三点:

  1. 我还声明了析构函数是虚拟的。这允许通过其基础 class 指针正确销毁对象。
  2. 我将基础 draw 方法声明为 pure-virtual(= 0 部分)。这意味着 Polygon class 是抽象的,它本身不能被实例化。您可能不希望这样,但对我来说,在基础 class 上使用绘制方法似乎毫无用处。如果需要,请定义一个。由你决定。
  3. override 说明符是可选的,但推荐使用(C++11 引入的语言特性)。它指示编译器您有意覆盖虚拟方法,因此如果不存在要覆盖的此类方法,则会生成编译器错误。

您需要在基础 class 中将函数定义为虚拟函数,并在子class 中覆盖它。例如

    #include <vector>
#include <iostream>
struct A{
    virtual void p(){std::cout<<"A ";}
    A(){}
    virtual ~A() {};
};
struct B: public A{
    void p()override{std::cout<<"B ";}
    B(): A(){}
};
struct C: public A{
    void p()override{std::cout<<"C ";}
    C() : A(){}
};
int main()
{
    A* a=new A();
    B* b=new B();
    C* c=new C();
    std::vector<A*> v={a,b,c};
    for(auto i : v)
    i->p();
    std::cout<<"\n";
    delete a;
    delete b;
    delete c;
    return 0;
}

打印“A B C”。