-3

I am a newcomer when its come to c++, when I study something about virtual functions and pure virtual functions, I found it's different than when I instantiate an object in different ways. This puzzles me a lot. I'll appreciate if you could help. The following are the codes and output.

#include <iostream>

using namespace std;

class A {
public:
    int va;
    int vb;

    virtual void m1() {
        cout << "this is A's m1() method" << endl;
    }

    void m3() {
        cout << "this is A's m3() method" << endl;
    }
};

class B : public A {
public:
    void m1() {
        cout << "this is B's m1() method" << endl;
    }

    void m2() {
        cout << "this is B's m2() method" << endl;
    }

    void m3() {
        cout << "this is B's m3() method" << endl;
    }
};

int main() {
    cout << "start" << endl;
    A a1 = B();
    a1.m1();
    a1.m3();
    cout << "===================" << endl;
    A *a2;
    a2 = new B();
    a2->m1();
    a2->m3();
    delete[]a2;
    /*
        output:
        this is A's m1() method
        this is A's m3() method
        ===================
        this is B's m1() method
        this is A's m3() method
    */
    return 0;
}

I'd like to know what's the difference between A a1 = B(); and A *a2; a2 = new B();. Thank you for doing the help.

Terence Simpson
  • 4,440
  • 2
  • 20
  • 18
Js_zero
  • 63
  • 7
  • Hint: When do `a1` and `a2` get destroyed? Also, you aren't instantiating anything. You only instantiate templates :) – Rakete1111 Mar 24 '18 at 16:05
  • Read a [good C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282) – Passer By Mar 24 '18 at 17:44
  • Compiler Explorer => http://godbolt.com/ There you can look into how *pointer type* works, how *vtable machanism* works in action. And also how objects get constructed on stack and on the heap. – sandthorn Mar 25 '18 at 07:44

2 Answers2

0

I'd like to know what's the difference between A a1 = B(); and A *a2; a2 = new B();.

A a1 = B(); will slice the B temporary to the A stack variable. Any additional member variables or behaviors of B will be discarded. The A stack variable a1 will be destructed at the end of the scope.

A *a2; a2 = new B(); will have a A pointer which points to a global store allocated B object. The a2 variable will point to that B object, which continues to be a B object. The virtual methods of A that are overridden in B will use the B methods. The non-virtual methods of A will be accessible through the A pointer, but the additional methods of B (virtual or non-virtual) will not be accessible, unless casting is used.

The delete[]a2; is undefined behavior, and on my machine will crash the application. Because the B object was allocated on the global store using new B(), it should be deleted using delete a2;.

Eljay
  • 4,648
  • 3
  • 16
  • 27
  • Thank you for answering my question, I've do some research after watching your answer, it is wrong for me to use delete[] here absolutely, but it's strange that my machine didn't crash on the application, by the way, my compiler is MinGW. – Js_zero Mar 25 '18 at 01:42
0

Do you happen to know/learn Java? Things work a bit different in C++.

A a1 is an object of type A, regardless of how you construct it. In particular:

A a1 = B();

Does the following:

  • creates a temporary object of type B
  • creates an object a1 of type A using a built-in copy constructor. It will copy the contents of the temporary to a1. Only the part A of the temporary will be copied though.
  • the temporary B object is destroyed.

That is why all methods on a1 are real A methods. No virtual mechanism will reach B's methods, because a1 is not a B-type object.


A* a2 on the other hand is a pointer to any object of type A or derivative. It is merely a pointer, on itself it does not represent an object.

Now, when you assign new B() to it, it will point to an object of actual type B. Calling virtual methods through this pointer will reach B's methonds as you probably expected.

btw. a single object referenced through a pointer should deleted through delete a2. You use delete [] a2 if you have an array.

CygnusX1
  • 20,968
  • 5
  • 65
  • 109