Question

Having class A, for example,

class A{
public:
    int x;
    void Update(){
        cout << " from a\n";
    }
};

In order to instantiate an object of A without calling the constructor, it goes like:

A* a = (A*) new char[sizeof(A)];

a->x = 9;
cout << a->x; a->Update(); //"9 from a" is outputted

now In case Update is a virtual function

class A{
public:
    int x;
    virtual void Update(){
        cout << " from a\n";
    }
};

It throw an "Access violation" exception, why ?

Was it helpful?

Solution

When a class declares one or more virtual functions, the compiler implicitly adds a V-Table pointer to the class declaration, and thereby, to each object.

For every virtual-function-call, the compiler generates code which reads the function's address from the object's V-Table pointer, and then jumps to that address.

The V-Table pointer of an object is initialized only during runtime, when the constructor of the class is called and the object is created.

So when you create an object without explicitly calling the object's class-constructor, the V-Table pointer of that object is not initialized.

Then, when you call a virtual function of that object, the CPU attempts to read the function's address from the object's V-Table pointer, and a memory access violation occurs.

OTHER TIPS

Calling a virtual function involves dereferencing the virtual function table pointer, stored within the object. It is dereferencing the place in memory where this value is supposed to be, but of course, it's uninitialized garbage, hence the error.

From the context of the question, it looks to me like you might be interested in Placement new. Placement new will allow you to re-use heap memory that has already been allocated, but will properly initialize the vtable pointer.

If you don't call the constructor of the object, then the virtual method table is not initialized. Therefore you can't expect calling a virtual function call to work. What are you trying to do in the first place >

Casting from an array of bytes into an object is only valid for POD types, that is, types that comply:

  • No user-defined destructor, constructor or copy operator.
  • Only public member variables.
  • No base classes.
  • No virtual functions.
  • No member variables of non-POD type, recursively.

That is, your first example is a POD, but your second one is not.

So your cast is valid for the first but not for the second. In the second case you will need to call placement new to construct a proper A object:

char *bytes = new char[sizeof(A)];
A *a= new (bytes) A;

And then, it is your responsibility to call the destructor when you are finished with it:

a->~A();

What are you expecting? Writing silly code results in silly results.

Anyway the objects need a virtual table - see What are you expecting? Writing silly code results in silly results. This table is not being initialised in the code supplied

See http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top