Оператор присваивания с наследованием и виртуальным базовым классом - PullRequest
1 голос
/ 07 января 2010

У меня есть абстрактный виртуальный базовый класс Foo, из которого я получаю множество других классов, которые незначительно отличаются. У меня есть фабрика, которая создает производные классы и возвращает Foo *. Одна из моих больших проблем связана с перегрузками операторов, я должен убедиться, что DFoo не работает от DFoo1 (не показано). В настоящее время я справился с этим, проверив, проваливается ли приведение, но я довольно недоволен этим подходом. Я должен использовать базовую реализацию, потому что я могу только вернуть базовый класс из фабрики. Если это лучший способ сделать это, это нормально, я просто хочу убедиться, что это имеет смысл, и что нет шаблона, который я пропускаю. Любые предложения о том, как обращаться с такими вещами, очень ценятся.

 class Foo
 {
    public:
          Foo(int x){...};
          Bar m_bar;
          virtual Foo& operator=(const Foo& f)
          {
             m_bar = f.m_bar
          }
 }

Теперь мой производный класс

class DFoo : public Foo
{
     DFoo(int x, int y):Foo(int x) {...}
     FooBar m_foobar;

     Foo& operator=(const Foo& rhs)
     {
        if(this != &rhs)
        {

              Foo::operator=(rhs);
              DFoo temp = static_cast<DFoo>(rhs);

              if(temp != NULL)
              {
                m_foobar = static_cast<DFoo>(rhs).m_foobar;
              }
              else
                 throw exception(ex);
        }
     }
}

Ответы [ 3 ]

1 голос
/ 07 января 2010

Самое умное в этой ситуации - объявить операторы присваивания и конструкторы копирования, но не определять их. Тогда, если где-то в вашем коде кто-то попытается сделать копию, он сгенерирует ошибку компоновщика. По сути это эффект boost :: nocopyable, за исключением того, что вы не используете внешнюю библиотеку для такой простой и тривиальной задачи.

Редактировать: Также, если вы сделаете конструктор и оператор приватными, вы получите ошибку компилятора.

1 голос
/ 07 января 2010

Вы никогда не должны делать это:

 class DFoo
 {
     Foo& operator=(const Foo& rhs) ;
 };

Если вы явно не хотите поддерживать присвоение базового класса производному типу (маловероятно).
Оператор assignemtn должен выглядеть следующим образом:

 class DFoo
 {
     DFoo& operator=(DFoo const& rhs);  // You can only assign DFoo to a DFoo.
                                        // Now there is no way for DFoo1 to get assigned to a DFoo
 };

Кроме того, в этом тривиальном примере, который вы разместили по умолчанию, был назначен оператор присваивания, сгенерированный компилятором. Есть ли какая-то особая причина, по которой вы пишете оператор присваивания?

1 голос
/ 07 января 2010

Вы, вероятно, ищете boost :: noncopyable .

...