【问题标题】:Is it bad to store the underlying type of an object?存储对象的底层类型是不是很糟糕?
【发布时间】:2022-07-21 16:58:14
【问题描述】:

如果我有一个名为Node 的类,如果Node 类的对象知道它们的NodeType 并且NodeType 将用于强制转换为这样的特定接口,那会很糟糕:

// NodeType

enum class NodeType : uint8_t
{
    None        = 0,
    Foo         = 1 << 0,
    Bar         = 1 << 1,
    FooBar      = 1 << 2,
    
    FooMask     = Foo | FooBar,
    BarMask     = Bar | FooBar,
};

inline constexpr uint8_t operator&(const NodeType& t_lhs, const NodeType& t_rhs)
{
    return static_cast<uint8_t>(t_lhs) & static_cast<uint8_t>(t_rhs);
}
// Base Node Class

class Node
{
public:
    virtual NodeType GetNodeType() const = 0;
};
// Interfaces

class IFoo
{
public:
    virtual ~IFoo() = default;

    virtual void FooSpecificMethod() const = 0;
};

class IBar
{
public:
    virtual ~IBar() = default;

    virtual void BarSpecificMethod() const = 0;
};
// Derived Node Classes

class FooNode : public Node, public IFoo
{
public:
    NodeType GetNodeType() const override { return NodeType::Foo; }

    void FooSpecificMethod() const override { std::cout << "Foo.\n"; }
};

class BarNode : public Node, public IBar
{
public:
    NodeType GetNodeType() const override { return NodeType::Bar; }

    void BarSpecificMethod() const override { std::cout << "Bar.\n"; }
};

class FooBarNode : public Node, public IFoo, public IBar
{
public:
    NodeType GetNodeType() const override { return NodeType::FooBar; }

    void FooSpecificMethod() const override { std::cout << "Foo.\n"; }

    void BarSpecificMethod() const override { std::cout << "Bar.\n"; }
};
// Use of NodeType and Interfaces

std::vector<std::unique_ptr<Node>> GetNodes()
{
    std::vector<std::unique_ptr<Node>> nodes{};

    nodes.push_back(std::make_unique<FooNode>());
    nodes.push_back(std::make_unique<FooNode>());

    nodes.push_back(std::make_unique<BarNode>());

    nodes.push_back(std::make_unique<FooBarNode>());
    nodes.push_back(std::make_unique<FooBarNode>());
    nodes.push_back(std::make_unique<FooBarNode>());

    return nodes;
}

int main()
{
    std::vector<std::unique_ptr<Node>> nodes{ GetNodes() };
    
    for (const auto& node : nodes)
    {
        if ((node->GetNodeType() & NodeType::FooMask) != 0)
            dynamic_cast<const IFoo*>(node.get())->FooSpecificMethod();
    }

    for (const auto& node : nodes)
    {
        if ((node->GetNodeType() & NodeType::BarMask) != 0)
            dynamic_cast<const IBar*>(node.get())->BarSpecificMethod();
    }
}

我的目标是在多态集合中的对象上做类型特定的事情,就像在最后一个代码 sn-p 中一样。这是一个不好的方法吗?有没有更多的面向对象的方法?

【问题讨论】:

    标签: c++


    【解决方案1】:

    这是一个不好的方法吗?有没有更多的面向对象的方法?

    是的。您可以将dynamic_cast 指向适当的指针类型并检查结果是否为空。

    int main()
    {
        std::vector<std::unique_ptr<Node>> nodes{ GetNodes() };
        
        for (const auto& node : nodes)
        {
            if (auto foo = dynamic_cast<const IFoo*>(node.get()))
                foo->FooSpecificMethod();
        }
    
        for (const auto& node : nodes)
        {
            if (auto bar = dynamic_cast<const IBar*>(node.get()))
                bar->BarSpecificMethod();
        }
    }
    

    【讨论】:

    • 是的,我知道这一点,但不想依赖启用RTTI,我想让转换为C-Style casts 变得容易,以防dynamic_casts 伤害我性能
    • @SamoChreno 你需要dynamic_cast,因为接口不是具体类型的第一个基础
    猜你喜欢
    • 2022-01-24
    • 2020-01-29
    • 2012-02-17
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 2016-08-10
    • 1970-01-01
    相关资源
    最近更新 更多