2012-07-03 4 views
1

У меня есть объект базового класса, который на самом деле, указывая на производный класс, как этотC++ передавая объект по ссылке и литье

Base *b = new Derived() 

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

Dummy_cast_fn(&b) // casts b to derived class 

После вызова Dummy_cast_fn, b должны иметь полную копию производного класса (без нарезки).

Редактировать Я не понимаю, какая часть не существует, поскольку указатели используются. Моя проблема: класс Derived возвращается из вызова функции в общую библиотеку, и у меня нет доступа к файлу .h для Derived. Только у меня есть информация о том, что Derived основан на базовом классе. У меня есть доступ к Base.h, поэтому я могу создать экземпляр объекта Base, но проблема возникает, когда я пытаюсь получить доступ к функциям, которые определены в Derived, но не в Base. Поэтому мне было интересно, могу ли я приводить тип Base в Derived, тогда я смогу получить доступ к функции, определенной в Derived, а не в Base.

+0

Вы хотите полную копию или ссылку на оригинал? – justin

+0

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

+0

Я хочу полную копию Derived. –

ответ

3

Пока b указатель или ссылка на Derived, вы всегда можете:

  1. Вниз бросить его на Derived.
  2. Рассматривайте это как Base, пока вы используете b.

А именно то, что определяет, что вы можете сделать с b является статическим типом, в этом случае Base. Однако, поскольку он фактически указывает на Derived, вы всегда можете его понизить. Тем не менее, чтобы использовать его как Derived, вы должны иметь переменную, тип которой равен Derived.

Итак, если цель Dummy_cast_fn заключается лишь в том, чтобы что-то исправить в b - это бесполезно. Если объект нарезается, ничто не может его исправить. Но в вашем случае нет нарезки, поскольку вы используете указатели.

Редактировать согласно редактировать на вопрос по:

Во-первых, вы Derived объект не вырезается. Давайте получим это со стола.У вас есть указатель на полный Derived (при условии, что вы прошли), но у вас есть доступ к его части Base при использовании указателя Base. Теперь вы говорите, что у вас нет определения Derived. Это означает, что вы не сможете сбрасывать этот тип, потому что компилятор не знает, как он определяется. Никакое кастинг не будет работать здесь. Не существует законного метода C++, который можно назвать функцией sum, если у вас нет определения Derived.

Я задаюсь вопросом, почему автор Derived предоставил вам свою документацию без предоставления ее определения. При таком виде полиморфизма поставщик обычно позволяет пользователю иметь некоторый «интерфейс», оставив фактический тип в качестве внутренней детали реализации. Если вы не можете использовать Derived, потому что у вас нет его определения, нет смысла давать вам документацию.

+0

Мне удалось получить дополнительную информацию об этом. Вся идея заключается в создании плагиновой системы, которая может вызывать плагин из общей библиотеки без включения файла .h, поэтому не требуется перекомпиляции, когда в систему добавляется новый плагин. Подумайте о плагине как возможностях, где возможности можно добавлять и загружать, анализируя список подкаталогов, чтобы найти, какие возможности нужно загружать. Все плагины будут базовыми для базового класса, для которого доступно определение. Подумайте об этом как о чем-то похожем на импорт в Java или Python ... –

+0

@VivekKhurana, именно поэтому предоставляется только база. Это интерфейс плагина, и это единственное, что должен знать пользователь. Как именно плагин предоставляет функциональность, это бизнес плагина. Если этот метод 'sum' должен быть частью функциональности плагина, он должен быть добавлен в' Base'. Обратите внимание, что импорт Java не будет работать, если импортированный класс недоступен. Единственное отличие состоит в том, что в Java есть отражение, которое может обойти определение и исследовать неизвестный тип. У вас этого нет в C++. – eran

2

Вы не можете изменить Base* в Derived*, но вы можете получить Derived*, указывающий на объект, что Base* который указывает, используя dynamic_cast:

Derived* d = dynamic_cast<Derived*>(b); 
if (d) { 
    // cast was succesful 
} else { 
    // cast failed, 
    // e.g. because b* does not point to a Derived* but some other derived type 
} 
2

Вы не можете изменить тип вашей Base* b , вы можете создать новый указатель

Derived* p = static_cast<Derived*>(b); 

и использовать это. Как только b объявлен как Base*, вы не можете изменить его тип. Вы также можете использовать dynamic_cast, хотя это происходит медленнее и может не быть строго необходимым (хотя я не могу сказать наверняка - это зависит от ваших требований). И если вы правильно используете виртуальные функции, которые вы можете даже не нужно делать любое приведение - это одна из целей полиморфизма