抽象基类的替代方案用于存储

时间:2018-06-14 21:27:35

标签: c++ polymorphism c++17 static-polymorphism

我想知道运行时多态的可用替代方法,特别是在我的类之间有一个公共基类的替代方法,以便存储派生类的实例并与之交互。 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;

1 个答案:

答案 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或绘制子弹时都不会发生。