Использование «правила нуля», когда у меня есть указатели на полиморфизм - PullRequest
0 голосов
/ 10 февраля 2019

Для «правила нуля» я понимаю, что хочу разделить управление данными на простые классы, реализующие правило 3, правило 5, что угодно, чтобы более сложные классы могли использовать конструкторы, операторы присваивания и т. Д., как автоматически предоставляется.

Как это работает, когда член класса должен быть указателем из-за полиморфизма?

Например, предположим, у меня есть класс

class MyClass{
private:
 s_array<int> mynumbers;
 s_array<double> mydoubles;

 Base * object;
 ...
 };

Здесь Base является базовым классом с несколькими производными классами, а object может указывать на один из производных классов.Так что object является указателем для получения полиморфизма.

Если бы не присутствие этого указателя Base, я мог бы использовать правило нуля для MyClass, предполагая s_array<> правильно реализовано.Есть ли способ настроить все так, чтобы MyClass мог использовать правило нуля, даже если объект является указателем?Поведение, которое я хочу при копировании, заключается в том, что новый экземпляр MyClass получает указатель на новую копию object.

Ответы [ 3 ]

0 голосов
/ 10 февраля 2019

Если несколько MyClass объектов могут указывать на один и тот же Base объект, тогда просто используйте std::shared_ptr<Base> вместо Base* для вашего object члена, как упоминали другие респонденты.

Но,если каждый объект MyClass должен указывать на свой собственный объект Base, то у вас нет другого выбора, кроме как реализовать правило 3/5 в MyClass, чтобы он мог создать свой собственный объект Base и / или клонBase объект от другого MyClass объекта.

0 голосов
/ 10 февраля 2019

Просто для записи, что я использую для решения этого, это следующее (в основном, как предложено выше):

template <class myClass>
class clone_ptr
{
public:
  clone_ptr(){location=nullptr;}
  clone_ptr(myClass* d) { location = d;}  
  ~clone_ptr() { delete location; } 

  clone_ptr(const clone_ptr<myClass>& source){
    if (source.location!=nullptr){
      location=source.location->Clone();
    }
    else
      location=nullptr;
  }
  clone_ptr& operator= (const clone_ptr<myClass>& source){
    if (&source!=this){
      if (source.location!=nullptr){
    location=source.location->Clone();
      }
      else
    location=nullptr;
    }
    return *this;
  }

  myClass* operator->() { return location; }
  myClass& operator*() { return *location; }

private:
  myClass* location;
};

Я реализую функцию Clone () в соответствующих классах следующим образом:

class myClass : public parentClass{
...
 public:
   myClass* Clone() 
   {
     return new myClass(*this);
   }
0 голосов
/ 10 февраля 2019

Если вы хотите применить правило 0 с указателями, вам нужно использовать общий указатель:

shared_ptr<Base> object; 

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

Чтобы получить желаемое поведение, вам нужно создать собственный умный указатель, который предусматривает правило 3 или 5.

...