Override function in C ++ not working

#include <cstdio> using namespace std; class A { public: virtual void func() { printf("A::func()"); } }; class B : public A { public: virtual void func() { printf("B::func()"); } }; int main() { A a = *(A *)new B(); a.func(); } 

The question is simple: why a->func() calls a function in class A , although A contains an object of class B?

+6
c ++ function override inheritance polymorphism
source share
7 answers
 A a = *(A *)new B(); a.func(); 

Here, what happens in this code, step by step:

  • new B() : a new object of type B is allocated in free storage, resulting in its address
  • (A*) : the address of the object is added to A* , so we have a pointer of type A* , which actually points to an object of type B that is valid. All OK.
  • A a : here the problems begin. A new local object of type A is created on the stack and created using the copy constructor A::A(const A&) , the first parameter being the object created earlier.
  • The pointer to the original object of type B is lost after this statement, which leads to a memory leak, since it was allocated in free storage using new .
  • a.func() - the method is called in the (local) object of class A.

If you change the code to:

 A& a = *( A*) new B(); a.func(); 

then only one object will be created, its pointer will be converted to a pointer of type A* , then dereferenced, and a new link will be initialized using this address . Then the call to the virtual function will be dynamically resolved to B::func() .


But remember that you still need to free the object since it was allocated with new :

 delete &a; 

Which, incidentally, will only be correct if A has a virtual destructor for which B :: ~ B () is required (which, fortunately, is empty here, but in the general case it is not necessary) will also be called. If A does not have a virtual destructor, then you need to free it:

 delete (B*)&a; 

If you want to use a pointer, then this is the same as with a link. The code:

 A* a = new B(); // actually you don't need an explicit cast here. a->func(); delete (B*)a; // or just delete a; if A has a virtual destructor. 
+13
source share

The problem you are facing is classic object splitting :

 A a = *(A *)new B(); 

Make a link or pointer to a , and the virtual submission will work as you expect. See this other question for further explanation.


You commented on another answer: "The compiler should at least give a warning or what." This is why it is considered good practice to make base classes either abstract but not copyable: your source code would not be compiled in the first place.

+5
source share

Now that you have changed the code snippet, the problem is obvious. Polymorphism (i.e. virtual functions) is called only by pointers and links. You have neither one nor the other. A a = XXX does not contain an object of type B , it contains an object of type A You "chopped" the B th property of an object by following this decree and dereferencing the pointer.

If you do A *a = new B(); , you will get the expected behavior.

+5
source share

This can do the trick.

 A &a = *(A *)new B(); a.func(); 

or

 A *a = new B(); a->func(); 
+1
source share

Virtual dispatch only works with pointers or reference types:

 #include <cstdio> using namespace std; class A { public: virtual void func() { printf("A::func()"); } }; class B : public A { public: virtual void func() { printf("B::func()"); } }; int main() { A* a = new B(); a->func(); } 
+1
source share

The problem is respect and casting from B to A with new A (*) (A *) new B ();

You can fix this by simply deleting * (A *), changing it to (A * a = new B ();), but I would do it even further, since your variable name is not suitable for instance B.

It should be

 B *b = new B(); b->func(); 
0
source share

Since you performed a slice when copying a dynamically allocated object to an object a type a (which also gave you a memory leak).

a should be a reference ( A& ) instead or just keep a pointer.

0
source share

All Articles