2010-11-03 4 views
14

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

class Parent 
{ 
    ... 
}; 

class Child : public Parent 
{ 
    ... 
}; 

class Factory 
{ 
    static Parent GetThing() { Child c; return c; } 
}; 

int main() 
{ 
    Parent p = Factory::GetThing(); 
    Child c1 = p; // Fails with "Cannot convert 'Parent' to 'Child'" 
    Child c2 = (Child)p; // Fails with "Could not find a match for 'TCardReadMessage::TCardReadMessage(TCageMessage)'" 
} 

Я знаю, что это должно быть простым, но я не уверен, что я делаю неправильно.

+0

Я не понимаю, что делает Фабрика. Похоже, что он возвращает локальную переменную. Является ли этот объект действительным? – John

+4

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

+0

Да, метод GetThing в классе Factory возвращает локальную переменную. Который, видимо, не будет делать то, что я хочу. Вместо этого я должен использовать указатели. По крайней мере, согласно ответам ниже. – Mykroft

ответ

15

A Parent объект возвращается по значению не может может содержать любые данные Child. Вы должны работать с указателями, предпочтительно смарт-указатели, так что вам не придется убирать за собой:

#include <memory> 

class Factory 
{ 
    // ... 

public: 

    static std::auto_ptr<Parent> GetThing() 
    { 
     return std::auto_ptr<Parent>(new Child()); 
    } 
}; 

int main() 
{ 
    std::auto_ptr<Parent> p = Factory::GetThing(); 
    if (Child* c = dynamic_cast<Child*>(p.get())) 
    { 
     // do Child specific stuff 
    } 
} 
+1

GetThing должен [вернуть auto_ptr] (http://stackoverflow.com/q/1837665/54262) (или аналогичный). Затем вы можете назначить возвращаемое значение непосредственно в интеллектуальный указатель или использовать метод release auto_ptr. – 2010-11-03 17:32:56

+0

GetThing() должен быть общедоступным. – bjskishore123

+0

Во-первых, 'Child * c' в выраженном выражении. Вы пропустили '*'. Во-вторых, «динамический_cast» для downcasting требует полиморфного типа. Типы OP не известны как полиморфные. Если 'Parent' не является полиморфным, ваш код не будет компилироваться. – AnT

1

Вы не можете, на самом деле. Ваш завод возвратил Parentобъект, который был построен из объекта Childc [*]. Детскую часть его уже отрезали, так как она возвращается в функцию main. Невозможно восстановить его.

Возможно, вы хотите использовать указатели?

[*] Кроме того, Child c(); объявляет функцию, она не определяет объект. Но это не ваш реальный код, и я думаю, ваш реальный класс имеет параметры конструктора.

+0

Да, извините, это правильное предположение о конструкторе. – Mykroft

-1

Вы не можете создавать фактические объекты, но вы можете указывать указатели на объекты.

Чтобы привести указатели использовать такой код:

Child* c = reinterpret_cast<Child*>(p); 
+2

Я бы порекомендовал 'dynamic_cast' –

+0

Согласен с max - reinterpret_cast можно рассматривать как« последнее заклинание »:) – Flexo

+0

Почему я должен использовать dynamic_cast или reinterpret_cast вместо того, чтобы просто сказать« Child * c = (child *) p; ' – Mykroft

0

Вы не можете бросить объект родительского класса типа класса ребенка. Объект родительского класса ... ну, объект родительского класса. Класс child extends родительский класс, что означает, что объект родительского класса обычно «меньше», чем объект дочернего класса. По этой причине кастинг (или реинтерпретация) родительского класса в качестве дочернего класса не имеет никакого смысла.

Объясните, что вы пытаетесь сделать. Без объяснений ваш вопрос просто не имеет смысла.

2

Я думаю, что проблема заключается не в том, как вы пытаетесь сделать актерский состав, а в том, почему вы хотите бросить в первую очередь. Код не имеет смысла - даже если он был синтаксически действителен. Вы пытаетесь превратить «плод» в «яблоко» в контексте, где легко доказать, что на самом деле у вас нет яблока. Динамические приемы и аналогичные эффекты полезны только тогда, когда у вас есть указатель на «плод», что у вас есть причины для этого, также является «яблоком».

+0

Этот код является лишь примером, показывающим соответствующие части того, как мой код объединяется. Это не мой фактический производственный код. – Mykroft

0

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

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

Я довольно удивлен, кстати, что вы не получили ошибку компилятора на GetThing(), потому что вы объявили c как функцию, чтобы вы не возвращали родителя.

Кроме того, кстати, если вы копируете значением вы «срез», таким образом:

Child c; 
Parent p(c); 
Child & c2 = dynamic_cast< Child& >(p); // throws bad_cast 
0

См кода ниже:

Child* c = dynamic_cast<Child*>(parentObject); 

где parentObject имеет тип Parent*

Убедитесь, что «parentObject» на самом деле имеет тип «Child», иначе неопределенное поведение.

Refer for More Info

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