Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Parnet and Derived class and Virtual confusion

42 views
Skip to first unread message

arnuld

unread,
Jan 24, 2018, 7:19:22 AM1/24/18
to

#include <iostream>

class Base
{
virtual void method() {std::cout << "from Base" << std::endl;}

public:
virtual ~Base() {method();}
void baseMethod() {method();}
};

class A : public Base
{
void method() {std::cout << "from A" << std::endl;}
public:
~A() {method();}
};

int main(void)
{
Base* base = new A;
base->baseMethod();
delete base;
return 0;
}

==================== OUTPUT =============================
[arnuld@arch64 programs]$ g++ -std=c++17 -pedantic -Wall -Wextra
virtual.cpp
[arnuld@arch64 programs]$ ./a.out
from A
from A
from Base
[arnuld@arch64 programs]$


See if my understanding is correct, lets walk through:

1) A new /Base type/ is created. It was allocated memory of derived
class /A type/. Implicit cast was performed by compiler. Constructors of
both /A/and /Base/ are called but they do not exist and hence nothing
happens.

2) base->baseMethod() is called which calls method(), it prints "from
Base".

3) /delete/ calls the destructor of /Base/, it prints "from Base" again.

But that does not happen.



-- arnuld
http://lispmachine.wordpress.com/

asetof...@gmail.com

unread,
Jan 24, 2018, 8:04:52 AM1/24/18
to
Possible I make one error is some time not use C++

But where is the problem

int main() {Base base; base.baseMethod();return 0;}
?

Thiago Adams

unread,
Jan 24, 2018, 8:08:46 AM1/24/18
to
Even if you don't write the constructor it exists. The constructor
we write (user-constructor) are not the real constructor.
The real constructor calls the inner objects constructor and
user-constructors and fills the vtable.


> 2) base->baseMethod() is called which calls method(), it prints "from
> Base".

No. "base->baseMethod();" prints "from A" . The vtable is ready at
this moment pointing to A::Method.


> 3) /delete/ calls the destructor of /Base/, it prints "from Base" again.
>
> But that does not happen.

It's dangerous and unclear to call virtual functions
at constructor and destructor.

I never do that I don't know if the standard gives you some
guarantee. I think vtable is "edited" officially at ctor and dtor.
You can explicitly call A::method() or Base::Method at ctor and dtor
is much more clear.



Öö Tiib

unread,
Jan 24, 2018, 8:24:52 AM1/24/18
to
Calling virtual functions from constructors and destructors is well
defined in C++ but your approach is more correct.

Basically at the time when base class subobject destructor is called
the more derived object is destroyed and so the base class is
most derived object at that moment and so Base::method() is
called as method().

However it is bad idea to do such "well-defined call" since people
will be confused with that and explicit fully qualified non-virtual
call Base::method() tells them lot better what is going on.

Juha Nieminen

unread,
Jan 24, 2018, 8:33:17 AM1/24/18
to
Thiago Adams <thiago...@gmail.com> wrote:
> It's dangerous and unclear to call virtual functions
> at constructor and destructor.

I don't think it's "dangerous" per se. The behavior is well defined:
The base class constructor will only call its own virtual function
implementations because the derived class has not been constructed yet.
The base class destructor will do likewise because the derived class
part has already been destructed.

It *can* lead to surprises when you aren't aware of this, sure, but
I wouldn't say it's "dangerous".

Alf P. Steinbach

unread,
Jan 24, 2018, 9:46:43 AM1/24/18
to
On 1/24/2018 2:08 PM, Thiago Adams wrote:
>
> It's dangerous and unclear to call virtual functions
> at constructor and destructor.

In Java and C#, yes. Not in C++.


Cheers & hth.,

- Alf

Thiago Adams

unread,
Jan 24, 2018, 12:33:27 PM1/24/18
to
On Wednesday, January 24, 2018 at 12:46:43 PM UTC-2, Alf P. Steinbach wrote:
> On 1/24/2018 2:08 PM, Thiago Adams wrote:
> >
> > It's dangerous and unclear to call virtual functions
> > at constructor and destructor.
>
> In Java and C#, yes. Not in C++.
>

I would like to add that I also find confuse
and bad to call virtual functions from base class
in even in other functions than ctor and dtor.

The problem caused is code coupling. You create
and dependency and you cannot review the code
locally.

Öö Tiib

unread,
Jan 24, 2018, 1:42:39 PM1/24/18
to
I do not understand the point about review. When we have dynamically
polymorphic tree of classes then there likely is good reason for it.
That reason is typically that we want to use (and dynamically exchange)
different objects through same interface without knowing the actual
types.

There is relatively useful pattern to separate two concerns of such
interface. Convenient interface of base class (through what the users
of that polymorphic tree use it) is one concern, "template" of virtual
functions (that the derived classes have to fill) is other concern.
These concerns sometimes coincide but not as rule and even not too
commonly. When these are not same then it is easier to make the
"template" virtual functions private and call these from public
"interface" non-virtual functions of base class.

That pattern can be misused to over-engineering (as can every pattern
or feature) but it more commonly simplifies work. When we review
"interface" we can concentrate on how simple is to use it. When
we review implementation of derived class we are only concerned how
accurately the "template" is filled.
0 new messages