2017-01-12 5 views
-2

Я пытаюсь сделать что-то вроде кода ниже. Note - класс, который наследуется от BaseModel. В какой-то момент я присваиваю экземпляр BaseModel экземпляру Note, но позже, когда я попытаюсь вернуть начальную ноту, кажется, что это невозможно.Почему я не могу отбрасывать из базового класса в дочерний класс в C++?

std::vector<Note> notes; 

Note note; 
notes.push_back(note); 

BaseModel model = Note(); // OK 
notes.push_back(model); // Error even though `model` is a `Note` 
Note note2 = (Note)model; // Also error, cannot get the `Note` instance back 

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

+1

Обратите внимание, что ваша инициализация 'model' уже будет обрабатывать объекты ...' model' не 'Note'. Попробуйте добавить конструктор в 'Note', который принимает в качестве аргумента const-baseModel' const. Тогда вы, вероятно, поймете, что здесь происходит. – hyde

+0

'notes.push_back (модель); // Ошибка, хотя модель - это записка. Хм, нет, это не так. Вы объявили модель как «BaseModel». (Я предполагаю, что ваше соглашение об именах является разумным и что 'BaseModel' является базой' Note') – Borgleader

+1

_I знаю, что я мог бы заставить его работать с указателями, но я хотел бы понять, почему он не работает со ссылками. _ ** ** работает со ссылками. Вы ** ** не используете ссылки. –

ответ

3

Ваш код показывает отсутствие понимания C++ по мере того, как идут объекты. Имея указатель на объект и работа с объектом ОЧЕНЬ по-разному в C++.

Посмотрите на объект, разрезающий, как предлагает Гайд. Трудно сказать, где именно вас путают, но какое-то еще исследование будет хорошим.

Я предполагаю, что BaseModel является базовым классом Note?

Если да: Когда вы делаете BaseModel model, вы не создаете примечание, даже если вы его инициализируете из примечания. Вы создаете новую BaseModel. Это не бросок, это создание новой вещи. Это немного похоже на это:

int a; 
float b = a; 

б не является ИНТ, он не указывает на междунар, он просто инициализируется из междунар. Это совершенно новый поплавок, который не имеет ничего общего с «а».

После этой строки у вас есть одно примечание (примечание) и полностью несвязанная BaseModel (модель).

Когда вы пытаетесь поместить модель в свой вектор, компилятор правильно информирует вас о том, что вы не можете этого сделать, поскольку BaseModel не является примечанием, и у вас есть вектор Notes.

Надеюсь, что вы указываете в правильном направлении.

+0

Спасибо, сравнение float/int в частности проясняет это. –

5

Значения в C++ являются значениями. Это не так на многих языках; они заставляют вас использовать только ссылки.

Предположим, что ваш базовый тип содержит один int snd, ваш производный тип имеет 2. Когда вы храните экземпляр производного в базе, нет места для второго целого числа.

Как известно, нарезка происходит; базовая часть производного сохраняется в базовом значении.

Вы не можете вернуться к производным, поскольку данные были отброшены.

Это практично; но в модели C++ значение базы типов - это точно база типа. Даже если тип dericed имеет одинаковый размер, его сохранение в значении базы типов дает вам значение базы типов. Там нет никакого производного объекта, всегда базового объекта.

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

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

Эти таблицы также позволяют проверять отливку на основание до производного.

+0

Спасибо, это имеет смысл. Итак, если я хочу сделать что-то вроде вопроса, это единственное решение использовать указатели и вектор указателей? –

+1

@ this.lau_ Или ссылки. Они тоже работают. Однако я не уверен, что у вас могут быть векторы ссылок. –

+1

@ this.lau_ Только решение? Нет, вы могли бы сделать какое-то странное стирание стилей, включающее полиморфизм типа ценности. Только разумное решение? Да. Используйте 'std :: unique_ptr ' 'в вашем' vector', если вам нужен полиморфизм. Если вам нужно сделать * копии * элементов, добавьте метод 'virtual std :: unique_ptr clone() const' для' Node' и переопределить в дочерних элементах. – Yakk

0

Я думаю, вы просто имеете его наоборот: Note является BaseModel. Это не означает, что обратное верно.

 Смежные вопросы

  • Нет связанных вопросов^_^