Home > front end >  Compiler casts derived instance as parent abstract class
Compiler casts derived instance as parent abstract class

Time:03-25

I have a bug in a project I am making where I am trying to use abstract classes. I have an abstract class defined as follows:

class BoundingVolume: public Displayable{

public:

    virtual bool intersects(BoundingVolume const& bv) const noexcept = 0;

    virtual bool intersects(Sphere const& sp)const noexcept = 0;

    virtual bool intersects(AABB const& aabb) const noexcept= 0;

    virtual float getVolume() = 0;

    virtual std::tuple<std::vector<std::array<float,3>>, std::vector<std::vector<unsigned int>>> &toMesh() = 0;
};

I am using it as a member of another class because in that class I don't know what derived class of it I want to use:

class Object{
public :
    explicit Object(std::vector<Point> const& vertices) noexcept;

    std::vector<Point> m_vertices;
    BoundingVolume *m_bounding_volume;
};

The code of my constructor for Object :

m_vertices = vertices

AABB aabb(points); // AABB is a derived class of BoundingVolume
auto aabb_pt = (AABB*) malloc(sizeof(AABB));
    *aabb_pt = aabb;

 m_bounding_volume = aabb_pt;

The problem is that when I construct an instance of Object and call toMesh on its BoundingVolume member, the program crashes (exit code 139). And while debugging it seems that it is because at the last line of my constructor the compiler makes a cast which does not allow it to understand later that m_bounding_volume is an instance of a derived class. What am I doing wrong? Am I understanding everything correctly? What should be changed?

CodePudding user response:

You should not be using malloc to allocate memory for this class. In C , objects might need additional logic to construct that isn't encapsulated by malloc, and this is especially, extremely true for objects that have inheritance, since [in most common implementations] the compiler has to do hidden work to construct the extra member data required to hold its type information.

In C , you should be using the new keyword instead:

m_vertices = vertices

AABB aabb(points); // AABB is a derived class of BoundingVolume
auto aabb_pt = new AABB(aabb); //Assuming that you do intend to allocate a copy of aabb, and not merely point to it
//If you just wanted a pointer to aabb, this would be more appropriate
//auto aabb_pt = &aabb;

 m_bounding_volume = aabb_pt;

It's also good practice in C to prefer using smart pointers, like std::unique_ptr or std::shared_ptr/std::weak_ptr, as these allow you to express ownership semantics and will help prevent these kinds of mistakes.

  •  Tags:  
  • c
  • Related