0

所以这是交易,我认为我需要就我正在使用的模式采取另一条路线,但我认为我会先获得一些专家意见。

我有一个类(UsingClass),它维护一个基类指针的动态列表。向列表中添加新对象时,我必须弄清楚它是什么类型的对象,因为我不能真正让它以多态方式工作。下面的行标记为“这不会像我想要的那样工作!!” 理想情况下,将多态地使用感兴趣的派生类中的 = 运算符,但不幸的是,它只使用 Base 类的默认 = 运算符......如果我将 Base 设为纯虚拟(基本上将其用于没有它自己的数据成员),但我真的不想让派生类拥有两者之间共有的成员(也许我只需要减少诱饵并做到这一点)。

我想我可能只是完全使用了错误的模式,但我不知道应该考虑哪些替代方案。

我知道代码不一定可以编译,但请与我合作。提前致谢!

    //code block
class Base { 
  protected: 
    int x;   
    float y;  
    string type;   // default to Derived1 or Dervied2 depending on the object inst  

  public:
    virtual int functionM(int l) = 0; 
    int functionN(int P);  
};  

class Derived1 : public Base { 
  protected:  
    int a;  

  public:  
   int functionM(int l); 
   float functionR(int h);  
};  

class Derived2 : public Base {  
  protected: 
     int b;  
     float r;  

  public: 
    int functionM(int l); 
    float functionR(int h); 
}; 

#define MAX_ARRAYSIZE   10 

class UsingClass { 
  private: 
    Base* myDerived1And2DynamicList[MAX_ARRAYSIZE];
    int indexForDynamicList;   

  public: 
    void functionAddDerivedToList(*Base myInputPtr) {  
       if((indexForDyanmicList + 1) < MAX_ARRAYSIZE) {  
           if(myInputPtr->type == "Derived1") {  
                myDerived1And2DynamicList[indexForDyanmicList+1] = new Derived1;  
                *myDerived1And2DynamicList[indexForDyanmicList+1] = *myInputPtr; // THIS WILL NOT WORK LIKE I WANT IT TO!!  
            } else if (myInputPtr->type == "Derived2") { 
                myDerived1And2DynamicList[indexForDyanmicList+1] = new Derived2;  
                *myDerived1And2DynamicList[indexForDyanmicList+1] = *myInputPtr; // THIS WILL NOT WORK LIKE I WANT IT TO!!  
            } 
        }  
     } // end of void function 
};
4

3 回答 3

3

您可以简单地向“Base”类添加一个虚函数并调用它,而不是检查类型。这会将 void functionAddDerivedToList(*Base myInputPtr) 简化为以下内容:

void functionAddDerivedToList(*Base myInputPtr)
{
   if((indexForDyanmicList + 1) < MAX_ARRAYSIZE) {  
       myDerived1And2DynamicList[indexForDyanmicList+1] = myInputPtr->clone();
   }
}

将始终实现克隆以调用类的复制构造函数。所以在 Base 中,添加以下内容:

virtual Base* clone() = 0;

实现将始终采用这种形式(示例是 Derived1,在您的示例中是 Base 的子类):

virtual Base* clone() { return new Derived1(*this); }
于 2011-07-22T04:03:02.033 回答
0

我看到的一个问题是您正在使用 C 风格的数组来包含“基础”对象的列表。请注意,在这种情况下,数组中元素的大小将是 sizeof(Base),这与 sizeof(Derived1) 和 sizeof(Derived2) 不同。两个派生也可能不同。在这种情况下,您可以做的是让数组包含 Base 对象的指针,而不是实际对象。这将使大小统一为 4 个字节,您可以将数组中的对象作为指针访问。因为数组现在包含指针,如果您只是想将它们插入数组中,则不必确定类型。

void functionAddDerivedToList(Base* myInputPtr)
{
    if((indexForDyanmicList + 1) < MAX_ARRAYSIZE)
        myDerived1And2DynamicList[indexForDyanmicList+1] = myInputPtr;
}

如果你想从数组中访问对象,你可以这样做。

Base* p = myDerived1And2DynamicList[index];
p->MyMethod();

您可以相信,在这种情况下,将根据 p 的实际类型调用正确的 MyMethod 函数。

于 2011-07-22T04:48:21.637 回答
0

我有一个类(UsingClass),它维护一个基类指针的动态列表。

对不起,但你没有(错误的语法)。但不要那样做。

首先,给你的Base类一个虚拟析构函数。否则你会遇到内存泄漏。

然后,重新设计您的UsingClass容器。给它一个指向 Base 成员的 shared_pointer 向量来保存动态分配的多态对象。(如果您使用非 C++0x 编译器,则可以使用std::tr1::shared_ptr.)

class UsingClass { 
private: 
  std::vector<std::shared_ptr<Base> myList;
  // int indexForDynamicList; is now myList.size()  

public: 
  void Add(Base* myInputPtr) {  
    myList.push_back(myInputptr);
  }
// ...
};

要添加多态对象,请使用

UsingClass container;
container.add(new Base);
container.add(new Derived1);
container.add(new Derived2);

您可以通过迭代调用所有多态方法

for (size_t i = 0; i < myList.size(); ++i)
{
  myList->functionM();  // give the function a more "speaking" name
} 

通过使用shared_ptr,您可以保存多个指向一个对象的指针,而不必关心释放内存。复制指针不会复制对象(所谓的浅拷贝)。如果您确实还需要复制对象(所谓的深度复制),您的Base派生类将必须实现一个虚拟clone()方法。

于 2011-07-22T07:28:28.367 回答