首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >没有指针的C++多态性

没有指针的C++多态性
EN

Stack Overflow用户
提问于 2011-08-28 20:14:08
回答 3查看 29.4K关注 0票数 43

编辑:这方面的一个更好的标题是:不需要单独的堆分配的大型对象集合的多态性。

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

有什么设计模式可以用来实现这一点吗?

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

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

回答 3

Stack Overflow用户

发布于 2015-02-20 11:42:11

我意识到这个问题很老,但我找到了一个有点不错的解决办法。

假设:

您预先知道所有的派生类(给定您的编辑,这是正确的)。

技巧:

使用boost::variant (0/doc/html/variant.html)

示例类:

代码语言:javascript
运行
复制
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;
    }
};

示例变体/访问者:

代码语言:javascript
运行
复制
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;
    }
};

示例用法:

代码语言:javascript
运行
复制
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();
    }
}

示例输出

代码语言:javascript
运行
复制
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!
票数 9
EN

Stack Overflow用户

发布于 2011-08-28 21:32:16

对于包含每个案例所需的超级数据集的联合,您可能可以使用一个简单的包装类来完成一些操作。这将包含一个指向共享策略对象的指针,该对象包含不同行为的代码。所以cat是PolyAnimal类的对象,speciesName = "cat",PredatorFeedingStrategy等等。

解决潜在问题的一个更好的方法可能是为更自然的设计设置适当的自定义分配器

票数 0
EN

Stack Overflow用户

发布于 2022-10-28 15:19:20

如果所有可能的子类都是在编译时已知的(这种情况也称为“封闭集多态”),这是对使用变体(无论是Boost的还是自cxx17以来的STL )的建议的后续跟进。

必须使用访问者模式访问对象的接口有点烦人(imo),这就是为什么我编写了一个公开基类接口(甚至基类操作符)的变体类型。它可以在变体中找到(需要C++17,因为它是围绕std::variant构建的)。

从@Draziv克隆示例:

类-定义

代码语言:javascript
运行
复制
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;
    }
};

示例用法

代码语言:javascript
运行
复制
pv::polymorphic_variant< Animal, Dog, Cat > variant;
variant->eat();

variant = Cat{};
variant->eat();

输出:

代码语言:javascript
运行
复制
Mmh, tasty bone!
Mmh, tasty fish!
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7223613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档