如何在C ++中强制实例化另一个对象(取决于它)中的对象

时间:2014-10-26 14:41:38

标签: c++ design-patterns

我手中有这种情况:

  1. 对象A取决于对象B(及其后代)中的一个或多个。
  2. 对象A和B可以有多个实例。应该将其插入到某个列表中(在对象A内部以向量形式存在B对象的列表)。
  3. 对象B(及其后代)不能存在于另一个对象和特定于对象A的唯一对象中。
  4. 因此,对象B不能在对象A之外实例化。
  5. 如果对象A已经实例化,它可以动态创建对象B(及其后代)的实例,并将其推入对象B的向量中。
  6. 对象A和对象B都可以无限地导出到许多变体中。
  7. 到目前为止,我已经提出了两个解决方案,而且我认为它们都没有错。

    解决方案#1:

      

    使用经理+工厂类创建并配对对象A和   B.还将管理对象A的列表/向量。

    这个问题是: 1.我需要将经理+工厂对象的实例经常传递给需要实例化对象A和B的任何对象。 2.因为我无法确定将来会有多少对象A和B的变体,我无法进行切换/案例实例化。或者如果我们采用工厂模式的方式,我必须强制要求对象A和B的每个子项都应该有一对工厂类。有点乏味,如果你问我,可能会使应用程序膨胀。 3.它不能强制执行上述规则的第3和第4点。除非我隐藏构造函数并使它们成为私有/受保护,并将经理+工厂类作为朋友类。

    解决方案#2:

      

    使对象A自我管理并将其引用存储到静态成员中   创造时的矢量。必须仅通过方法创建对象B.   名为“AddB()”,它将模板类作为输入,   在方法内部,它将实例化模板类并将其存储到向量中   对象B。

    这个问题是: 1.我无法确保输入的模板类实际上是对象B的子/派生,因为它毕竟是一个模板。 2.很可能会增加一些性能,因为它毕竟是一个模板。仅供参考,我可能需要经常进行实例化,即使是2000左右。 3.它仍然无法执行上述规则的第3和第4点。除非我隐藏构造函数并使它们成为private / protected,并将A类作为B类的友元类。

    那么,关于如何以最好的方式解决这个问题的想法呢?

    提前致谢。

1 个答案:

答案 0 :(得分:1)

对我来说,它看起来像“因此,对象B不能在对象A之外实例化。”是问题的关键。

模板路由可能是最好的,因为如果类不是向量类型的子类,它会生成编译时错误。我还让每个B(动物)类成为A的朋友,所以A可以使用私有构造函数。它在封装时吃掉了,可能很难维护,但它确实有效。

示例:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Farm;
class Animal {
    protected:
    Animal() {}
    public:
    virtual ~Animal() {}
    void makeSound() { cout << this->sound() << endl; }
    virtual string sound () const = 0;
    friend class Farm;
};

class Cat : Animal {
    protected:
    Cat() {}
    public:
    virtual ~Cat() {}
    virtual string sound () const { return "meow"; }
    friend class Farm;
};


class Dog : Animal {
    protected:
    Dog() {}
    public:
    virtual ~Dog() {}
    virtual string sound () const { return "bark"; }
    friend class Farm;
};

class Tractor {
    protected:
    Tractor() {}
    virtual ~Tractor() {}
    virtual string sound () const { return "rummm!"; }
    friend class Farm;
};


class Farm {
    vector< Animal * > animals;

public:
    template< typename AnimalType >
    void create() {
        animals.push_back( new AnimalType );
    }

    void disturbAnimals() {
        for( auto animal : animals ) {
            animal->makeSound();
        }
    }
};


int main( int argc_, char ** argv_ ) {
    Farm farm;
    farm.create<Cat>();
    farm.create<Dog>();

    // Generates compile-time error
    //farm.create<Tractor>();
    farm.disturbAnimals();

    return 0;
}