Why the output is like this?

Hello,
I have such code and I don't know where the second A.f in output comes from. I suppose the first is from new A(), but don't have a clue about the second.

Here is the output: A.f A.f B.f M ~A.f

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>

using namespace std;

class A
{
public:
    virtual void f()
    {
        printf("A.f ");
    }
    A()
    {
        f();
    }
    ~A()
    {
        printf("~A.f ");
    }
};

class B: public A
{
public:
    A *a;
    void f()
    {
        printf("B.f ");
    }
    B(A *a=nullptr)
    {
        f();
        this->a=a;
    }
};

int main()
{
    A *a=new B(new A());
    printf("M ");
    delete a;
    return 0;
}
Calling delete on "a" calls the destructor for A (and only A, since the destructor is not virtual*).

https://www.geeksforgeeks.org/destructors-c/

A destructor function is called automatically when the object goes out of scope:
(1) the function ends
(2) the program ends
(3) a block containing local variables ends
(4) a delete operator is called


*Note: If your destructor is virtual and therefore can be overidden, calling delete a; will also call the B's dtor and then A's dtor.

NOTE: Your program can have undefined behavior.
In function 'int main()':
41:12: warning: deleting object of polymorphic class type 'A' which has non-virtual destructor might cause undefined behaviour [-Wdelete-non-virtual-dtor]

To fix this, you need to mark your A class as having a virtual destructor

1
2
3
4
    virtual ~A()
    {
        printf("~A.f ");
    }
Last edited on
Thank you for such a quick reply. Actually I am wondering about :

A.f (A.f) B.f M ~A.f


Where (A.f) comes from.
Last edited on
A.f (A.f) B.f M ~A.f

Where (A.f) comes from.


First, new A() calls f(). This is the first A.f.
Then, new B() implicitly calls the default constructor for A() as its being created, since B is a subclass of a A. This is the second A.f.

The base class is always constructed before the subclass.

Also, here's an example showing differences in behavior when the destructor is virtual:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>

using namespace std;

class A
{
public:
    A()
    {
        printf("A ");
    }
    ~A()
    {
        printf("~A ");
    }
};

class B : public A
{
public:

    B()
    {
        printf("B ");   
    }
    ~B()
    {
        printf("~B ");   
    }
};

class Avirt
{
public:
    Avirt()
    {
        printf("Avirt ");
    }
    virtual ~Avirt()
    {
        printf("~Avirt ");
    }
};

class Bvirt : public Avirt
{
public:

    Bvirt()
    {
        printf("Bvirt ");   
    }
    ~Bvirt()
    {
        printf("~Bvirt ");   
    }
};

int main()
{
    printf("start of main\n");
    
    printf("Not virtual: ");
    A *a = new B();
    delete a;
    
    printf("\nVirtual: ");
    Avirt *avirt = new Bvirt();
    delete avirt;
    
    printf("\nend of main\n");
    return 0;
}

start of main
Not virtual: A B ~A 
Virtual: Avirt Bvirt ~Bvirt ~Avirt 
end of main

Notice no ~B is called.

(Also I edited my original post just a bit to make it a bit more clear)
Last edited on
Topic archived. No new replies allowed.