C++ c++;确保将对象指定给一组对象

C++ c++;确保将对象指定给一组对象,c++,C++,我在写一个建模与仿真程序时遇到了一个设计问题。模型的所有组件都被组织成一个树型数据结构,为了使其工作,每个组件都需要有一个指向其父对象的指针。为了避免技术细节,我做了一个类比: 我有一个处理所有树功能的基类: class node {}; 以及以下表示仿真组件的派生类: class turtle : public node {}; class clam : public node {}; class dog : public node {}; class leg : public node

我在写一个建模与仿真程序时遇到了一个设计问题。模型的所有组件都被组织成一个树型数据结构,为了使其工作,每个组件都需要有一个指向其父对象的指针。为了避免技术细节,我做了一个类比:

我有一个处理所有树功能的基类:

class node {};
以及以下表示仿真组件的派生类:

class turtle : public node {};
class clam : public node {};
class dog : public node {};
class leg : public node {
  node* _parent;
  /*Some functions relevant to a leg*/
};

class shell : public node {
  node* _parent;
  /*Some functions relevant to a shell*/
};
还有其他子组件:

class turtle : public node {};
class clam : public node {};
class dog : public node {};
class leg : public node {
  node* _parent;
  /*Some functions relevant to a leg*/
};

class shell : public node {
  node* _parent;
  /*Some functions relevant to a shell*/
};
我的问题是,我想确保腿只分配给乌龟或狗,壳只分配给乌龟或蛤蜊。dog类没有处理
shell
类型的子类的功能,同样,clam也不能处理
leg
类型的子类


我正在考虑制作
shell
leg
类模板,它们的父类型将是模板参数。然后,我可以只为我希望每个类具有的父类型专门化构造函数模板。这是解决这个问题的好方法,还是我应该看一些其他C++特性? 您可以为可用的功能和属性提供接口,并根据需要将它们混合在一起。在C++中使用纯虚函数< /P>创建接口
class leg;
class shell;

struct IAnimalWithShell {
    void addShell(shell* shell) = 0;
    ~IAnimalWithShell() = default;
};

struct IAnimalWithLegs {
    void addLegs(const std::vector<leg*>&) = 0;
    ~IAnimalWithLegs() = default;
};
类腿;
类外壳;
结构IAnimalWithShell{
void addShell(shell*shell)=0;
~IAnimalWithShell()=默认值;
};
结构IAnimalWithLegs{
void addLegs(const std::vector&)=0;
~IAnimalWithLegs()=默认值;
};

class-turtle:public节点、public IAnimalWithShell、public IAnimalWithLegs{
// ...
公众:
void addShell(shell*shell){
//实施
}
void addLegs(const std::vector和legs){
//实施
}
};
clam类:公共节点,公共IAnimalWithShell{
// ...
公众:
void addShell(shell*shell){
//实施
}
};

class-dog:public节点,公共IAnimalWithLegs{
// ...
公众:
void addLegs(const std::vector和legs){
//实施
}
};
我希望你能明白

当您要求设计时,以下是一些相关的模式


这些讨论了如上所述的结构化设计的后果。

您可以为可用的功能和属性提供接口,并根据需要将它们混合在一起。在C++中使用纯虚函数< /P>创建接口
class leg;
class shell;

struct IAnimalWithShell {
    void addShell(shell* shell) = 0;
    ~IAnimalWithShell() = default;
};

struct IAnimalWithLegs {
    void addLegs(const std::vector<leg*>&) = 0;
    ~IAnimalWithLegs() = default;
};
类腿;
类外壳;
结构IAnimalWithShell{
void addShell(shell*shell)=0;
~IAnimalWithShell()=默认值;
};
结构IAnimalWithLegs{
void addLegs(const std::vector&)=0;
~IAnimalWithLegs()=默认值;
};

class-turtle:public节点、public IAnimalWithShell、public IAnimalWithLegs{
// ...
公众:
void addShell(shell*shell){
//实施
}
void addLegs(const std::vector和legs){
//实施
}
};
clam类:公共节点,公共IAnimalWithShell{
// ...
公众:
void addShell(shell*shell){
//实施
}
};

class-dog:public节点,公共IAnimalWithLegs{
// ...
公众:
void addLegs(const std::vector和legs){
//实施
}
};
我希望你能明白

当您要求设计时,以下是一些相关的模式


这些讨论了上述结构设计的后果。

我个人会将约束检查代码转移到专用的工厂类,例如:

class TurtleFactory {
public:
    node * newTurtle() const {
        node * t = new turtle;
        for (int i = 0; i < 4; ++i)
            t->addChild(new leg);
        t->addChild(new shell);
        return t;
    }

    friend class turtle;
    friend class shell;
    friend class leg;
};
每只海龟还可以计算添加的部件数量,以禁止添加超出允许范围的部件:

    virtual bool canAdd(Type t) { 
        if (t == LEG && nLegs < 4) return true;
        else if (t == SHELL && nShell < 1) return true;
        else return false;
    }
virtualboolcanadd(类型t){
如果(t==LEG&&nLegs<4)返回true;
else如果(t==SHELL&&nShell<1)返回true;
否则返回false;
}

我个人会将约束检查代码移动到专用的工厂类,例如:

class TurtleFactory {
public:
    node * newTurtle() const {
        node * t = new turtle;
        for (int i = 0; i < 4; ++i)
            t->addChild(new leg);
        t->addChild(new shell);
        return t;
    }

    friend class turtle;
    friend class shell;
    friend class leg;
};
每只海龟还可以计算添加的部件数量,以禁止添加超出允许范围的部件:

    virtual bool canAdd(Type t) { 
        if (t == LEG && nLegs < 4) return true;
        else if (t == SHELL && nShell < 1) return true;
        else return false;
    }
virtualboolcanadd(类型t){
如果(t==LEG&&nLegs<4)返回true;
else如果(t==SHELL&&nShell<1)返回true;
否则返回false;
}

您的示例可能与源任务不同,但我应该提到:

您不能从
leg
继承
turtle
,因此只能通过组合将
leg
类插入到
turtle
类中。这意味着
turtle
用户不能直接访问
leg
类方法,您应该在
turtle
和/或其父类中实现它们。或者,正如在另一个答案中所说,使用接口

我认为完成这门课的最好方法是:

1) 将
leg
类中的所有方法设为私有,以禁用直接继承和/或合成

2) 创建一个新的类
LegMoving
,它是朋友类,用于
,并且知道如何控制
leg
将成为
LegMoving
类的成员

3) 继承
turtle
LegMoving


我认为这样您就不会违反基本OOP模式。

您的示例可能与源任务不同,但我应该提到:

您不能从
leg
继承
turtle
,因此只能通过组合将
leg
类插入到
turtle
类中。这意味着
turtle
用户不能直接访问
leg
类方法,您应该在
turtle
和/或其父类中实现它们。或者,正如在另一个答案中所说,使用接口

我认为完成这门课的最好方法是:

1) 在
leg
类privat中设置所有方法
class turtle 
: public node
, public legs<turtle,4>
, public shell<turtle> {
public:
     turtle() 
     : legs<turtle,4>({leg(),leg(),leg(),leg()})
     , shell<turtle>(false) {
     }
     void doMoveForward(size_t legIndex) {
         // Let the base implementation check the range first
         legs<turtle,4>::doMoveForward(legIndex);

         // Call the specific behavior
         legs_[legIndex]->moveForward(10); // at slow speed
     }
};
class clam 
: public node
, public shell<clam> {
public:
     clam() : shell<clam>(true) {
     }
    void doOpenShell() {
         // Implementation
    }
};
class dog 
: public node
, public legs<dog,4> {
public:
     dog() : legs<dog,4>({leg(),leg(),leg(),leg()}) {
     }          
     void doMoveForward(size_t legIndex) {
         // Let the base implementation check the range first
         legs<dog,4>::doMoveForward(legIndex);

         // Call the specific behavior
         legs_[legIndex]->moveForward(100); // at fast speed
     }
};