将成员动态添加到C++类的解决方法

Iam*_*Iam 3 c++ oop


我想知道你将如何解决这个问题:

我有一节课Foo:

class Foo
{
public:
    Foo()  {   }
    ~Foo() {   }
    float member1() { return _member1; }
private: 
    float _member1;
    // other members etc...
}
Run Code Online (Sandbox Code Playgroud)

一个容器类,除其他外,它包含一个指向Foo实例的指针容器

class FooContainer
{
public:
   FooContainer() {   }
   ~FooContainer() {   }
   void addFoo(Foo* f) {_foos.push_back(f);}
private:
   boost::ptr_vector<Foo> _foos;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:在运行时我需要向Foo"添加"新的(完全不同的)成员,具体取决于GUI的指令.我可以通过创建这样的两个"装饰器"来解决这个问题:

class Decorator1
{
public:
   int   alpha() { return _alpha; }
   float beta()  { return _beta; }
private:
   int _alpha;
   float _beta;
}

class Decorator2
{
typedef std::complex<float> cmplx;
public:
   cmplx  gamma() { return _gamma; }
   double delta()  { return _delta; }
private:
   cmplx  _gamma;
   double _delta;
}
Run Code Online (Sandbox Code Playgroud)

然后我会创建两个不同的Foo实现:

class Foo1 : public Foo, public Decorator1 
{   }

class Foo2 : public Foo, public Decorator2 
{   }
Run Code Online (Sandbox Code Playgroud)

并根据GUI命令使用每一个.但是这样的改变将通过我的所有代码传播,并会迫使我建立两个不同的版本,使用每个类Foo1Foo2(如我不得不创建FooContainer1FooContainer2).

一种不那么具有侵入性的方法就是创造

class Bar: public Foo, public Decorator1, public Decorator2
{   }
Run Code Online (Sandbox Code Playgroud)

并使用它代替Foo.在这种情况下,我会打电话给我只能从需要的功能Decorator1Decorator2而忽略其他,但这似乎违背良好的面向对象技术.

关于这个问题的任何建议?

Per*_*est 8

你为什么不使用像这样的简单多态?

class Foo
{
public:
    Foo()  {   }
    virtual ~Foo() {   }
    float member1() { return _member1; }
private: 
    float _member1;
    // other members etc...
}

class Foo1 : public Foo
{   
    public:
   int   alpha() { return _alpha; }
   float beta()  { return _beta; }
private:
   int _alpha;
   float _beta;
}

class Foo2 : public Foo
{   
    typedef std::complex<float> cmplx;
public:
   cmplx  gamma() { return _gamma; }
   double delta()  { return _delta; }
private:
   cmplx  _gamma;
   double _delta;
}

class FooContainer
{
public:
   FooContainer() {   }
   ~FooContainer() {   }
   void addFoo(Foo* f) {_foos.push_back(f);}
private:
   boost::ptr_vector<Foo> _foos;
}
Run Code Online (Sandbox Code Playgroud)

然后客户端代码不需要更改.根据GUI命令,您可以创建Foo1或Foo2并将其添加到单个容器中.如有必要,可以使用Foo指针上的dynamic_cast转换为Foo1或Foo2.但是,如果您已正确编写客户端代码,则不需要这样做.