没有指针的C++多态

And*_*tan 31 c++

假设我有一个基类Animal与虚函数和一些派生类(Cat,Dog等).实际派生类包含4-8个字节的数据.我想存储一个std::list<Animal>实际上包含派生对象的项目.我想避免使用new在堆上创建许多小对象.

有没有可用于实现此目的的设计模式?

编辑:我的想法来实现这一点

  1. 创建std::deque<Cat>,std::deque<Dog>...; std::list<Animal*>包含指针的商店deques; 我使用的是std::deque因为我认为它具有良好的内存管理和大量的对象;

Nic*_*las 33

最终,没有.

多态性仅适用于非值类型:引用和指针.由于引用只能绑定一次,因此您无法在标准容器中使用它们.这给你留下了指针.

你在错误的一端攻击这个问题.如果你担心分配大量小对象的开销(我假设这是一个合理的问题.也就是说,你有实际的分析数据或足够的经验来知道它是你的特定应用程序的一个问题),然后你应该解决这个问题.更改为这些对象分配内存的方式.制作一个小的分配堆或其他东西.

不可否认,前C++ 0x的分配器在这方面有些缺乏,因为它们必须是无状态的.但为了您的目的,您应该能够处理它.


从你的编辑:

这是一个糟糕的主意.从删除std::deque任何地方,但起点或终点会作废每次在你的指针std::list.

鉴于您的评论,这个想法是有用的.但是,为不同类型的对象提供所有这些不同的内存块似乎违背了整个继承点.毕竟,你不能只写一种新的类型Animal并将它放入std::list; 你必须为它提供内存管理.

您确定基于继承的多态性是您需要的吗?你确定其他一些方法不能正常工作吗?


小智 6

我意识到这个问题已经过时了,但我找到了一个有点漂亮的解决方案.

假设:

您事先知道所有派生类(给定您的编辑,这是真的).

特技:

使用boost :: variant(http://www.boost.org/doc/libs/1_57_0/doc/html/variant.html)

示例类:

class Animal {
public:
    virtual void eat() = 0;
};

class Cat : public Animal {
    virtual void eat() final override {
        std::cout << "Mmh, tasty fish!" << std::endl;
    }
};

class Dog: public Animal {
    virtual void eat() final override {
        std::cout << "Mmh, tasty bone!" << std::endl;
    }
};
Run Code Online (Sandbox Code Playgroud)

示例变体/访客:

typedef boost::variant<Cat, Dog> AnimalVariant;

class AnimalVisitor : public boost::static_visitor<Animal&> {
public:
    Animal& operator()(Cat& a) const {
        return a;
    }

    Animal& operator()(Dog& a) const {
        return a;
    }
};
Run Code Online (Sandbox Code Playgroud)

用法示例:

std::vector<AnimalVariant> list;
list.push_back(Dog());
list.emplace_back(Cat());

for(int i = 0; i < 5; i++) {
    for(auto& v : list) {
        Animal& a = v.apply_visitor(AnimalVisitor());
        a.eat();
    }
}
Run Code Online (Sandbox Code Playgroud)

示例输出

Mmh, tasty bone!
Mmh, tasty fish!
Mmh, tasty bone!
Mmh, tasty fish!
Mmh, tasty bone!
Mmh, tasty fish!
Mmh, tasty bone!
Mmh, tasty fish!
Mmh, tasty bone!
Mmh, tasty fish!
Run Code Online (Sandbox Code Playgroud)