Как назначить объект базового класса для объекта производного класса? - PullRequest
3 голосов
/ 01 января 2011

Если у меня есть базовый класс A и общедоступный класс B, как мне назначить объект A подобъекту базового класса A в B?

class A {...};
class B : public A {...};
A a(..);
B b(..);
static_cast<A&>(b) = a; ???

Это выполнимо без написания оператора присваивания для B? Есть ли потенциальные проблемы с приведением b к A &? Это стандартное соответствие?

Ответы [ 6 ]

4 голосов
/ 02 января 2011

Написание еще одного ответа, чтобы продемонстрировать, почему и как назначить объект базового класса для объекта производного класса.

struct TimeMachineThing_Data {
..
..
};

class TimeMachineThing : private TimeMachineThing_Data
{
    static std::stack<TimeMachineThing_Data> m_stateHistory;

    void SaveState() {
        m_stateHistory.push_back( static_cast<TimeMachineThing_Data&>(*this) );
    }

    void RestoreState() {
        static_cast<TimeMachineThing_Data&>(*this) = m_stateHistory.front();
        m_stateHistory.pop_front();
    }
};

Это очень полезно и полностью допустимо.

(Вот частное наследование,так только внутренне TimeMachineThing IS-A TimeMachinetime_Data)


Еще один.

struct StructWithHundresField {
  string title;
  string author;
  ...

  StructWithHundresField() {
    ...
  }
};

class EasyResetClass : public StructWithHundresField {
  int not_reset_this_attriute;
public:
  void ResetToInitialStateAtAnyTime() {
    static_cast<StructWithHundresField&>(*this) = StructWithHundresField();
  }
}
4 голосов
/ 01 января 2011

Это действительно плохая идея.A является основой, B является производным типом.Приведя B к A, вы теперь используете оператор присваивания A, который не будет касаться каких-либо дополнительных производных данных.В конце этого присваивания b по-прежнему считается типом B, хотя теперь оно содержит A.Это противоположно тому, как должно использоваться наследование.

Изменение строки на b = reinterpret_cast<B&>(a); будет еще хуже.Тогда вы будете притворяться, что a - это B, когда это не так, и вы читаете недопустимую память.

Если вы действительно хотите выполнить такое назначение, вам нужно:

class B : public A {
    B& operator= (const A& a) { ... }
};

Затем вы можете написать функцию для копирования информации из A и каким-то образом работать с дополнительной информацией в производном типе B, плюс это позволит вам просто написать:

b = a;
2 голосов
/ 01 января 2011

Задумайтесь на минуту о том, хорошая ли это идея.Помните, что если у вас есть подкласс A B, то каждый B является A, но не каждый A является B. Например, каждая собака является млекопитающим, но не каждое млекопитающее является собакой.Если у вас есть конкретный объект B, попытка установить его на объект A в большинстве случаев не является математически четкой.Более того, в мире C ++, поскольку ваш объект B статически типизирован как B, вы никогда не сможете присвоить ему объект типа A таким образом, чтобы он перестал быть B. В лучшем случае вы собираетесь перезаписатьтолько часть A объекта B без изменения какой-либо части, специфичной для B.

1 голос
/ 01 января 2011

В C ++ (как и в других языках ООП) наследование устанавливает отношение Is-A.

То есть, если B публично наследует A, B = A.

Вы всегда можете привести экземпляр BСсылка без каких-либо забот.

0 голосов
/ 02 января 2011

Каждый должен знать, что присвоение является ковариантным двоичным оператором и поэтому не может корректно работать с виртуальными функциями.Это верно для большинства бинарных операторов, но присваивание является особенным, потому что оно является частью языка C ++.

Если вы используете OO, ваши объекты должны быть некопируемыми и всегда представлены указателями.Уникальность идентичности объекта является сердцем ОО: объекты не являются значениями, они имеют уникальное значение (их адрес).

Если вы играете со значениями, вы должны использовать соответствующие понятия: функциональное программирование (ФП).Это замыкания (аппликативные объекты), переключатели, шаблоны, варианты и другие вещи.

Постарайтесь получить четкое представление о каждом из них, прежде чем смешивать их.В общем случае FP включает в себя OO, так же как и общая методология: OO - это особый случай, который в особых обстоятельствах обеспечивает безопасную динамическую диспетчеризацию.OO диспетчеризация является линейной, что означает, что она обрабатывает неограниченный набор подтипов, но она также применяется только к свойствам (функциям с одним альтернативным аргументом, а именно объекту) и не может работать для чего-либо более высокого порядка (функции с более чем одним вариантным аргументом).Назначение - это просто еще одна 2-х функция, следовательно, ее нельзя передать виртуальными функциями.

0 голосов
/ 01 января 2011

Я бы сказал, что вам нужен оператор присваивания, который специально копирует объект A в объект B.

В общем, хорошая идея иметь любой способ при копировании объектов одного типа. Но объекты разных типов делают его еще более важным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...