Мартин рассказал вам, что пошло не так , вот что вы должны сделать вместо этого:
Bar bar;
Foo& foo = bar; // this works now
Теперь foo
является ссылкой к объекту, и вы можете иметь ссылки на базовый класс (и указатели, BTW), ссылающиеся на объекты производных классов.
Однако этот
bar = foo;
никогда не будет работать (по крайней мере, неявно) и не должен.Здесь вы пытаетесь назначить объект базового класса (или ссылку) производному классу.
Однако, хотя производный класс всегда может заменить объект базового класса, обратное неверно.(Вы не можете просто бездумно использовать любое транспортное средство , когда вам нужна лодка , потому что не все транспортные средства являются лодками,транспортное средство, которое вы используете, может быть автомобилем , и вы утонете.)
Это не означает, что вы не можете заставить его работать.если вы знаете, как создать объект производного класса из объекта базового класса, вы можете написать для этого функцию.Просто компилятор не знает, как сделать автомобиль из автомобиля .
Как показало solipist , такая функция преобразования может быть конструктором.Однако я хотел бы сделать конструкторы преобразования явными:
class Bar: public Foo
{
public:
explicit Bar(const Foo&);
//
}
Ключевое слово explicit
гарантирует, что компилятор никогда не попытается вызвать этот конструктор, если вы не скажете так.Если вы удалите его, то этот код скомпилирует:
//void f(Foo); // you meant to call this, but forgot to include its header
void f(Bar); // you didn't even know this was included
Foo foo;
f(foo); // won't compile with the above Bar class
, и компилятор сгенерирует этот код в молчании: f(Bar(foo));
Хотя это поначалу кажется удобным, я думаю, что рано или поздноукушенный каждым неявным преобразованием, я позволил проникнуть в мой код и позже должен был удалить их.Так много лет назад я поклялся никогда не допускать их.
Обратите внимание, что даже с конструктором преобразования explicit
вы все равно можете вызывать f(Bar)
с объектом Foo
- вы просто должны сказать это явно:
f(Bar(foo)); // compiles fine even with the explicit conversion constructor