Как я могу привести родительский класс в качестве дочернего класса - PullRequest
22 голосов
/ 03 ноября 2010

Прошло много времени с тех пор, как мне пришлось писать код на 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)'"
}

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

Ответы [ 8 ]

24 голосов
/ 03 ноября 2010

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
    }
}
3 голосов
/ 03 ноября 2010

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

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

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

2 голосов
/ 03 ноября 2010

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

0 голосов
/ 28 марта 2018

Вы можете приводить с помощью конструктора Single Argument: т.е. (родитель работает, ребенок изучает) следующим образом:

#include <iostream>
using std::cout;

class Parent
{
    public:
    void goToWork()
    {
        cout<<"working\n";  // only parents work
    }
};

class Child : public Parent
{
    public:
    Child(const Parent& parentAddr){}
    void goToSchool()
    {
        cout<<"studying\n";   // only children studies
    }
};

int main(void)
{
    Child child(*(new Parent()));

    // here's a child working
    child.goToWork();
    return 0;
}

вы передаете адрес дочернего класса в качестве параметра конструктора родителя и можете использовать дочерний объект objзаниматься родительским делом

0 голосов
/ 03 марта 2016

См. Фрагмент кода ниже:

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

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

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

См. Подробнее

0 голосов
/ 03 ноября 2010

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

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

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

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

Child c;
Parent p(c);
Child & c2 = dynamic_cast< Child& >(p); // throws bad_cast
0 голосов
/ 03 ноября 2010

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

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

0 голосов
/ 03 ноября 2010

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

Для создания указателей используйте код, подобный следующему:

Child* c = reinterpret_cast<Child*>(p);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...