我想知道运行时多态的可用替代方法,特别是在我的类之间有一个公共基类的替代方法,以便存储派生类的实例并与之交互。 RTP具有通过vtable查找进行间接寻址的缺点,并且还强制将派生类存储为指针,因此通常必须动态分配它们。据我所知,这阻碍了内联和编译器的优化。
总之,我不想要这个:
class Animal
{
public:
virtual void noise() const = 0;
};
class Dog : public Animal
{
public:
virtual void noise() override const {std::cout<<"Woof!\n";};
};
class Cat : public Animal
{
public:
virtual void noise() override const {std::cout<<"Meow!\n";};
};
//...
std::vector<Animal*> animals;
我想要这样的事情:
class Dog
{
public:
void noise() const {std::cout<<"Woof!\n";};
};
class Cat
{
public:
void noise() const {std::cout<<"Meow!\n";};
};
//...
std::vector<*Things that have noise()*> animals;
答案 0 :(得分:0)
在您的示例中,我无法帮助您,但对于具有数据成员的类,这是一个优化。
假设我们想创建一个子弹地狱游戏。
在一种天真的方法中,我们需要一个班级Bullet
:
class Bullet {
public:
void draw(Renderer& r);
virtual void update_logic(float delta);
void run_physics();
protected:
float vx, vy; //velocity
private:
float x, y; //position
//...
};
因此,将调用update_logic
方法来设置项目符号的速度,然后run_physics
将此速度应用于该位置。
修改逻辑需要多态性,因此您的集合变为std::vector<Bullet*>
(或现代c ++中的std::vector<std::unique_ptr<Bullet> >
)。
然后,在主循环中,首先更新逻辑,然后更新物理,然后绘制子弹。
当然,由于指针取消引用和vtables等,效率很低。
你能做的是:
class Bullet {
public:
void draw(Renderer& r);
void update_logic(float delta) { logic->update(delta); };
void run_physics();
void setVelocity(float, float);
void setLogic(BulletLogic*);
private:
float x, y, vx, vy;
BulletLogic* logic;
};
现在,你可以使用std::vector<Bullet>
,只有在更新逻辑时才会出现间接,但是在运行phyics或绘制子弹时都不会发生。