【问题标题】:How to create polymorphic object如何创建多态对象
【发布时间】:2014-10-08 01:16:15
【问题描述】:

我有一个类,它结合了一些结构,例如这样:

struct _tRack1{
    unsigned char shelf1;
    unsigned int shelf2;
    float shelf3;
};

struct _tRack2{
    char shelf1;
    int shelf2;
    char shelf3;
    char shelf4;
};

struct _tRack3{
    char shelf1;
    unsigned int drawer[5];
};
class Catalog
{
public:
    _tRack1 *localdata1;
    _tRack2 *localdata2;
    _tRack3 *localdata3;
    int index;
    Catalog(int recktype){
        localdata1 = NULL;
        localdata2 = NULL;
        localdata3 = NULL;
        index = recktype;
        switch(recktype){
            case 1: *localdata1 = new _tRack1; break;
            case 2: *localdata2 = new _tRack2; break;
            case 3: *localdata3 = new _tRack3; break;
        }
    };
    ~Catalog(){
        if(localdata1 != NULL) delete localdata1;
        if(localdata2 != NULL) delete localdata2;
        if(localdata3 != NULL) delete localdata3;
    };
    int someMethod(_tRack1){/*...*/};
    int someMethod(_tRack2){/*...*/};
    int someMethod(_tRack3){/*...*/};
};

int main()
{
    Catalog *foo = new Catalog(1);
    Catalog *bar = new Catalog(3);

    /*...*/
    if(foo->index>1) foo->localdata1->shelf1=-3;
       else foo->localdata1->shelf1=3;
    if(bar->index>1) bar->localdata1->shelf1=-3;
       else bar->localdata1->shelf1=3;
    if(bar->index==3) bar->localdata3->drawer[0] = 0xDEADBEAF;


    /*...*/
    delete foo;
    delete bar;
    return 0;
}

我知道公开结构并不好,但在现实生活中结构非常复杂,因此不可能创建访问不同结构字段的方法。 我想找到一种隐藏结构类型的方法。要访问这样的数据:

    if(foo->index>1) foo->data->shelf1=-3;
       else foo->data->shelf1=3;
    if(bar->index>1) bar->data->shelf1=-3;
       else bar->data->shelf1=3;
    if(bar->index==3) bar->data->drawer[0] = 0xDEADBEAF;

有可能吗?

【问题讨论】:

  • 为什么是多态...?
  • 您希望 Catalog 根据条件仅包含三个结构中的一个?我无法从代码中判断结构是否在逻辑上相互关联以建议基类。也许你可以只使用一个联合。
  • 嗯,工会?听起来不错,我试试……
  • 这不是问题,但if(foo->index>1) foo->localdata1->shelf1=-3; 会在 index==2 时触发分段错误!
  • 嗯,是时候读一本关于面向对象编程的书了。它不仅会提到多态性,还会提到封装。 :)

标签: c++ class oop polymorphism


【解决方案1】:

你应该扔掉你迄今为止所做的任何事情。然后读一本关于面向对象编程的书,然后从头开始。

简单来说,您应该创建一个基类 Rack,然后从它继承特定的 Rack 类型(即派生类)。 Catalog 或任何其他类都不应该知道从 Rack 派生的对象的详细信息。它应该要求 Rack 派生的对象通过调用它们的虚拟方法来执行操作,而不是要求/访问它们的私有详细信息。

此外-忘记新的存在并立即删除。你还不需要它。这会让你的代码变得更糟。

【讨论】:

    【解决方案2】:

    应该在 Catalog 中创建一个 get 方法,该方法可以在指定参数后返回结构体中的所有成员。 如:

    void Catalog::getValue(char* member, char &value)
    {
    switch(index)
    {
      case 2:
        if(member="shelf1") value = localdata2->shelf1;
        if(member="shelf3") value = localdata2->shelf3;
      break;
      case 3:
        if(member="shelf1") value = localdata3->shelf1;
      break;
      case 3: break;   
    }   
    }
    

    另一个浮动值等等。

    【讨论】:

      【解决方案3】:

      当您仅通过指针访问目录(项目)时,它非常适合抽象类。然后机架将从这个基类继承:

      class CatalogItem {   // I've just rename it not to confus with yours
      private: 
          int index;          // you need this 
      public: 
          CatalogItem(int recktype) : index(recktype) { }   
          int getType() { return index; }
          virtual ~CatalogItem() {}       // Virtal destructor so that the real class destructor is called
          virtual int someMethod() = 0;   // Pure virtual function.  You can never create object directly 
      };
      

      然后你可以创建你的结构或类_tRack1如下:

      class _tRack1 : public CatalogItem {
      public: 
          unsigned char shelf1;    // Original structure, but better'd hide it later
          unsigned int shelf2;
          float shelf3;
      
          _tRack1() : CatalogItem (1) {}; 
          int someMethod() { /* implementation for type 1 */ return 0; };
      };
      

      对 _tRack2 和 _tRack3 执行类似操作。你的主要看起来像:

      CatalogItem *foo = new _tRack1;  // pointer to a real consistent object
      CatalogItem *bar = new _tRack3;
      ...
      if (foo->getType()==1)  static_cast<_tRack1*>(foo)->shelf1 = 3; // object specific setting
      foo->someMethod();   // call of method.  You don't have to care about index anymore.  
      

      【讨论】:

        猜你喜欢
        • 2012-05-09
        • 2012-08-12
        • 1970-01-01
        • 1970-01-01
        • 2014-06-03
        • 1970-01-01
        • 1970-01-01
        • 2015-08-12
        • 1970-01-01
        相关资源
        最近更新 更多