protected destructor

1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class UPNumber
{
public:
	UPNumber()
	{
		cout << "UPNumber constructor called" << endl;
	};
protected:
	~UPNumber()
	{
		cout << "UPNumber destructor called" << endl;
	}
};

class derived_UPNumber: public UPNumber
{};

int main()
{
	UPNumber b;
}


The above the code does not compile, because destructor is protected.


2)
1
2
3
4
int main()
{
    derived_UPNumber d;
}

The above code compiles. I had expected that the derived class will call base class constructor (which is okay, since constrcutors are public) and when going out of scope, destructors will be called and coz dest is protected in the base class, the code will not compile.

Why is there a difference between first and second instances.
Children call their parents' ctors when constructed, as well as calling their parents' dtors when destructed. Since it's the child class which is calling the parent dtor, it has permission to do so because children have access to their parents' protected members.

::main only calls the destructor of the object as it's declared. In your second example, this is derived class' dtor -- which works because that is public by default.
In the second case, how would then a derived object destroy the base part of its object?

When derived object is declared:

- It calls base class constructor to instantiate base members
- It calls derived class constructor to instantiate derived members
- When it goes out of scopt, it calls derived class destructor to destroy derived members
- It calls base class destructor to destroy base members

Isn't this true?
Last edited on
All of those points are true, yes. However you're being a little vague by just saying "it calls". public/protected/etc depend on who is calling it. A protected dtor is possible to call as long as you have access to protected members of that class -- and children have access to their parent's protected members. This is why a child can call its parent's dtor, but a global function can't call that dtor.

dtor calling (as well as default ctor calling) is implied and it done automatically without you having to actually type it. To illustrate what's going on, here's an example which explicitly calls ctors and dtors.

This example shows what the compiler is doing behind the scenes:

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
class Parent
{
public:
  Parent()  // default ctor
  {}

protected:
  ~Parent()  // protected dtor
  { }
};

//---------------------------

class Child : public Parent
{
public:
  Child()      // child default ctor
    : Parent() // Child calls its parent's ctor at the start of its initializer list
                    //  you can do this explicitly, but if you don't, it is done automatically
  {
  }

  ~Child()   // the child's dtor
  {
    // ... destruction stuff here  ...

    // at the END of the dtor, the child then automatically calls it's parent's dtor:
    ~Parent();   // note you SHOULD NOT do this explicity -- this is just to illustrate
  }
};

//------------------

int main()
{
  Child a;  // Child::Child() called here
  return 0;  // Child::~Child() called here
} 


Note that main never calls Parent::anything, it only calls Child::X. Child::X calls all the parent functions, which is why it's okay if they're protected in this case. You could even make Parent ctor protected here, and it'd be fine, because Child (and not main) is calling the ctor.
Good to know. Most of the confusion occurred because the behavior is different for protected data members in base class (which cannot be accessed) and protected destructor in base class (which can be accessed via derived class destructor). Thanks.
Last edited on
Topic archived. No new replies allowed.