复合智能指针,不带dynamic_pointer_cast

时间:2014-06-21 04:07:23

标签: c++ design-patterns c++11 composite

我使用智能指针实现了复合模式,它一直有效。

问题是我只能使用接口中实现的方法,并且我不能使用派生类中定义的方法而不使用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;
}

它可以在live preview上看到,但是当我尝试使用时:

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;
}

我收到了错误:

  

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

提前致谢。

3 个答案:

答案 0 :(得分:2)

我认为这里的问题是它可以用于多态,但是母语类中不存在'getNew'方法,所以你需要定义它并使其成为虚拟的。这是在不使用对象的强制转换的情况下执行此操作的唯一方法。 有这条线它应该工作。

virtual void getNew() = 0;

答案 1 :(得分:1)

一种可能的解决方案是在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

答案 2 :(得分:1)

以下信息可以找到&#34; 复合模式 &#34;来自GOF书。当然,它已经基于图形类进行了解释。

复合模式的 抽象类 代表< / em> 原语 他们的容器 即可。对于图形系统,此类是Graphic。 Graphic声明了特定于图形对象的 Draw 等操作。 声明 所有复合对象共享 的操作,例如访问和管理其子级的操作。

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

//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; }
};