Home > Software design >  How to cast an object returned from a function in C
How to cast an object returned from a function in C

Time:09-25

In the virtual method create() in the derived class Derived, I return a struct of type HelpDerived. However, since I had to set the return type of the method to HelpBase, I found that I need to cast the returned object back to the type HelpDerived.

The following is an example of my case.


#include <iostream>


struct HelpBase {
    int a = 0;
    virtual void output() {}
};

struct HelpDerived : HelpBase {
    int b = 0;
    void output() override {}
};


class Base {
public:
    virtual HelpBase create() = 0;
};

class Derived : public Base {
public:
    HelpBase create() override;
};

HelpBase Derived::create() {
    HelpDerived d;
    d.a = 1;
    d.b = 2;
    return d;
}


int main() {
    Derived d;
    auto based = d.create();
    HelpDerived derived = dynamic_cast<HelpDerived &>(based);

    std::cout << derived.a << std::endl;
}

When I run the code abve, I get the error

terminate called after throwing an instance of 'std::bad_cast'
  what():  std::bad_cast
Abort trap: 6

What have I misunderstood about objects and casting in C ? Why does this method not work?

What can I do to fix the problem?

CodePudding user response:

I think you'd better return a pointer to avoid object slicing in your create function.

#include <iostream>


struct HelpBase {
    int a = 0;
    virtual void output() {}
};

struct HelpDerived : HelpBase {
    int b = 0;
    void output() override {}
};


class Base {
public:
    virtual HelpBase* create() = 0;
};

class Derived : public Base {
public:
    HelpBase* create() override;
};

HelpBase* Derived::create() {
    HelpDerived* d = new HelpDerived;
    d->a = 1;
    d->b = 2;
    return d;
}

int main() {
    Derived d;
    auto based = d.create();
    HelpDerived* derived = dynamic_cast<HelpDerived *>(based);

    std::cout << derived->a << " " << derived->b << std::endl;
    delete derived;
}

CodePudding user response:

I've replaced dynamic cast by static cast and it worked for me almost fine.

#include <iostream>


struct HelpBase {
    int a = 0;
    virtual void output() {}
};

struct HelpDerived : HelpBase {
    int b = 0;
    void output() override {}
};


class Base {
public:
    virtual HelpBase create() = 0;
};

class Derived : public Base {
public:
    HelpBase create() override;
};

HelpBase Derived::create() {
    HelpDerived d;
    d.a = 3;
    d.b = 2;
    return d;
}


int main() {
    Derived d;
    auto based = d.create();
    HelpDerived derived = static_cast<HelpDerived &>(based);

    std::cout << derived.a << std::endl;
    std::cout << derived.b << std::endl;
}

Output:

3

32726

Note that a value is correct, while b is junk. This is because for derived constructor has not been called. In general, casting from base class to derived is not recommended, as derived may have more data members, than base class. Recommended reading: https://www.bogotobogo.com/cplusplus/upcasting_downcasting.php

  • Related