从超类指针向量调用重写方法
Calling overridden methods from a vector of superclass pointers
我目前正在使用 C++ 在 OpenGL 中编写一个小游戏。来自 non-C++ 背景,我有一个关于覆盖方法以及如何使用 superclass 类型的指针调用它们的简单问题。
情况是这样的:我有一个 class Polygon
包含方法 void draw()
。这个 class 有两个 children,分别称为 Rectangle
和 Circle
,它们都覆盖了绘制方法,因为我根据绘制的多边形类型使用不同的 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"; }
};
注意以上三点:
- 我还声明了析构函数是虚拟的。这允许通过其基础 class 指针正确销毁对象。
- 我将基础
draw
方法声明为 pure-virtual(= 0
部分)。这意味着 Polygon
class 是抽象的,它本身不能被实例化。您可能不希望这样,但对我来说,在基础 class 上使用绘制方法似乎毫无用处。如果需要,请定义一个。由你决定。
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”。
我目前正在使用 C++ 在 OpenGL 中编写一个小游戏。来自 non-C++ 背景,我有一个关于覆盖方法以及如何使用 superclass 类型的指针调用它们的简单问题。
情况是这样的:我有一个 class Polygon
包含方法 void draw()
。这个 class 有两个 children,分别称为 Rectangle
和 Circle
,它们都覆盖了绘制方法,因为我根据绘制的多边形类型使用不同的 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"; }
};
注意以上三点:
- 我还声明了析构函数是虚拟的。这允许通过其基础 class 指针正确销毁对象。
- 我将基础
draw
方法声明为 pure-virtual(= 0
部分)。这意味着Polygon
class 是抽象的,它本身不能被实例化。您可能不希望这样,但对我来说,在基础 class 上使用绘制方法似乎毫无用处。如果需要,请定义一个。由你决定。 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”。