如何创建多态对象

时间:2014-08-14 11:39:39

标签: c++ class oop polymorphism

我有一个类,它将一些结构联合起来,例如:

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;

有可能吗?

3 个答案:

答案 0 :(得分:3)

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

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

而且 - 忘记现在存在新的和删除。你还不需要它。这会让你的代码变得更糟。

答案 1 :(得分:0)

应该在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;   
}   
}

和另一个浮动值等等。

答案 2 :(得分:0)

当您仅通过指针访问目录(项目)时,它是抽象类的一个很好的候选者。然后机架将从此基类继承:

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.