Michael Seibt
Michael Seibt

Reputation: 1346

Calling a virtual function of in-memory object

I'm trying to make an inline constructor for a class, which has a virtual function. For the overall purpose, the function has to be virtual because Shape::print will be called by another Class, not knowing what kind (exact type) of Shape it is addressing.

I see that this has to be some kind of memory relevant issue. How can I call this function when using my Class-Object not constructed but as a pointer? Or am I missing something else?

#include <stdio.h>
#include <stdlib.h>

using namespace std;

class Shape {
public:
    virtual void print(){};
};

class Circle : Shape {
private:
    int r;
public:
    Circle(int radius){
        this->r = radius;
    }

    // My "inline-constructor"
    static Circle* make(int radius){
        Circle* circ = (Circle*) malloc(sizeof(Circle));
        circ->r = radius;
        return circ;
    };

    virtual void print(){
        printf("%u", this->r);
    };
};

int main(){
    Circle circObj(5);
    circObj.print(); // Works fine    
    Circle* circPtr = Circle::make(10);
    circPtr->print(); // Crashes    
    return 0;
 }

Thanks in advance, any help is apreciated.

Upvotes: 0

Views: 149

Answers (3)

user207421
user207421

Reputation: 310893

// My "inline-constructor"
static Circle* make(int radius){
    Circle* circ = (Circle*) malloc(sizeof(Circle));
    circ->r = radius;
    return circ;
};

This isn't any kind of a constructor. It is just a wrongly written factory method. It should just consist of

return new Circle(radius);

which makes it so trivial as to be completely pointless.

How can I call this function when using my Class-Object not constructed but as a pointer?

Shape* shape = ....; // for example, new Circle(...)
shape->print();

No rocket science

Upvotes: 2

Rakib
Rakib

Reputation: 7625

The problem is, malloc just allocates enough raw memory and returns it. malloc does not initialize the created memory. So members of your object have to be initialized manually before use. You are doing it only for the r, but not for the member method print.

You should use new instead of malloc. new works in two steps

  1. Allocate enough memory using operator new ( equivalent task of malloc)
  2. Call constructor of the object to initialize it, which actually sets values for the member.

Upvotes: 1

anderas
anderas

Reputation: 5844

In you "inline-constructor", you are just allocating memory, not initializing it. For example, the vtable is not initialized, leading to a crash since print is virtual and its address is expected in the vtable.

Try Circle* circ = new Circle(radius); instead of malloc.

Upvotes: 3

Related Questions