与不带dynamic_pointer_cast的智能指针组合

Composite with smart pointers without dynamic_pointer_cast

本文关键字:智能 指针 组合 cast pointer dynamic      更新时间:2023-10-16

我使用智能指针实现了复合模式,它一直工作到某个点。

问题是,我只能使用在接口中实现的方法,我不能使用在派生类中定义的方法,而不使用dynamic_pointer_cast,我不想要它。

我想知道不使用dynamic_pointer_cast是否有可能做到这一点。

我听说我需要实现访问者模式,但我真的不知道如何实现,也不知道它是否适合这个问题。

#include <iostream>
#include <vector>
#include <memory>
class Fruit
{
public:
    virtual void getOld() = 0;
};
class Orange : Fruit
{
public:
    Orange() {}
    void add(std::shared_ptr<Fruit> f)
    {
        v.push_back(f);
    }
    std::shared_ptr<Fruit> get(int k)
    {
        return v[k];
    }
    void getOld()
    {
        std::cout << "Orange - I'm old." << std::endl;
    }
private:
    std::vector<std::shared_ptr<Fruit>> v;
};
class Bitter : public Fruit
{
public:
    Bitter() {}
    void getOld()
    {
        std::cout << "Bitter - I'm old." << std::endl;
    }
    void getNew()
    {
        std::cout << "Bitter - I'm new." << std::endl;
    }
};
int main(int argc, char ** argv)
{
    auto orange = new Orange;
    orange->add(std::make_shared<Bitter>());
    auto bitter = orange->get(0);
    bitter->getOld();
    return 0;
}

就像你在实时预览中看到的那样,它可以工作,但是当我尝试使用:

int main(int argc, char ** argv)
{
    auto orange = new Orange;
    orange->add(std::make_shared<Bitter>());
    auto bitter = orange->get(0);
    bitter->getOld();
    bitter->getNew();
    return 0;
}

I got errors:

错误:'class Fruit'没有名为'getNew'的成员

我认为这里的问题是,它将与多态性工作,但方法'getNew'不存在于母类,所以你需要定义它并使其虚拟。这是不使用对象强制转换的唯一方法。这条线应该行得通。

virtual void getNew() = 0;

一个可能的解决方案是在Orange中添加以下功能。

template <typename T>
T* get(int k)
{
    return dynamic_cast<T*>(v[k].get());
}

然后使用:

auto bitter = orange->get<Bitter>(0);
bitter->getOld();
bitter->getNew();

执行dynamic_cast,但被定位为Orange

关于"复合图案"的信息可以从GOF书中找到。当然,它已经在图形类的基础上进行了解释。

复合模式是一个抽象类, 两个原语他们的容器。对于图形系统,这个类是Graphic。Graphic声明了像Draw这样特定于图形对象的操作。它声明了所有复合对象共享的操作,例如访问和管理其子对象的操作。

根据以上解释,在使用复合模式时,我们应该理想地声明节点的叶子和非叶子(容器)类型的所有可能的接口。我认为这是必要的,以便让客户统一地处理单个对象和对象的组合。因此,理想情况下,在使用这种特定模式时,应该按照以下方式声明类。任何基于客户端代码中对象的确切类型编写的逻辑都违反了该模式的本质。

//Abstract class which should have all the interface common to
// Composite and Leaf class. It may also provide the default 
// implementation wherever appropriate.
class Fruit {
public:
    virtual void getOld() = 0;
    virtual void getNew() = 0;
    virtual void add(std::shared_ptr<Fruit> f) { }
    virtual  std::shared_ptr<Fruit> get(int index ) {return nullptr; }
    virtual ~Fruit() { }
};

//Composite Node
class Orange : Fruit {
public:
    Orange() {}
    void add(std::shared_ptr<Fruit> f) { v.push_back(f); }
    std::shared_ptr<Fruit> get(int k) { return v[k]; }
    void getOld()  { std::cout << "Orange - I'm old." << std::endl; }
    void getNew() { std::cout << "Orange - I'm new." << std::endl; } 
private:
    std::vector<std::shared_ptr<Fruit>> v;
};

//Leaf node
class Bitter : public Fruit {
public:
    Bitter() {}
    void getOld() { std::cout << "Bitter - I'm old." << std::endl; }
    void getNew() { std::cout << "Bitter - I'm new." << std::endl; }
};