полиморфизм с оператором = с использованием базового класса указателя - PullRequest
0 голосов
/ 22 июля 2011

Так что вот в чем дело, я думаю, что мне нужно пойти другим путем в отношении шаблона, который я использую, но я подумал, что сначала должен получить некоторые экспертные заключения.

У меня есть класс (UsingClass), который поддерживаетдинамический список указателей базового класса.При добавлении нового объекта в список я должен выяснить, что это за тип объекта, потому что я не могу заставить его работать полиморфно.Строка ниже с меткой "ЭТО НЕ БУДЕТ РАБОТАТЬ, КАК Я ХОЧУ, ЧТО ЭТО ХОЧУ !!"в идеале полиморфно использовать оператор = из интересующего класса Derived, но, к сожалению, он использует только оператор default = для базового класса .... вероятно, будет работать, если я сделаю Base чисто виртуальной (в основном, ограничив ее использование интерфейсом безсобственные данные), но я не хочу, чтобы классы Derived содержали членов, которые являются общими для обоих (возможно, мне нужно просто вырезать приманку и сделать это).

Я думаю, что я могу простополностью использовать неправильный шаблон, но я не знаю, какие альтернативы мне следует рассмотреть.

Я знаю, что код не обязательно компилируется, но, пожалуйста, работайте со мной.Заранее спасибо!

    //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 
};

Ответы [ 3 ]

3 голосов
/ 22 июля 2011

Вместо проверки типа вы можете просто добавить виртуальную функцию в класс '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); }
0 голосов
/ 22 июля 2011

У меня есть класс (UsingClass), который поддерживает динамический список указателей базового класса.

Извините, но у вас нет (неправильный синтаксис). Но не иди этим путем.

Сначала дайте вашему классу Base виртуальный деструктор. В противном случае вы будете испытывать утечки памяти.

Затем перепроектируйте ваш UsingClass контейнер. Дайте ему вектор shared_pointer члену Base для хранения динамически расположенных полиморфных объектов. (Если вы используете не 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().

0 голосов
/ 22 июля 2011

Одна проблема, которую я вижу, состоит в том, что вы поете в массиве в стиле C, который содержит список «базовых» объектов. Обратите внимание, что размер элементов в массиве в этом случае будет sizof (Base), который отличается от sizeof (Derived1) и sizeof (Derived2). Оба деривата также могут быть разными. В этом случае вы можете сделать так, чтобы массив содержал указатели базовых объектов вместо реальных объектов. Это сделает размер в форме до 4 байтов, и вы можете получить доступ к объектам в вашем массиве как указатели. Поскольку массив теперь содержит указатели, вам не нужно определять тип, если вы просто хотите вставить их в массив.

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

Если вы хотите получить доступ к объекту из массива, вы можете сделать что-то вроде этого.

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

Вы можете верить, что в этом случае будет вызываться правильная функция MyMethod на основе фактического типа p.

...