472,958 Members | 2,719 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,958 software developers and data experts.

Polymorphic behavior without virtual functions


What is the expected output of this program and why???

#include <iostream>

using namespace std;

class base
{
public:
~base() {cout << "base" << endl;}
};

class derived: public base
{
public:
~derived() {cout << "derived" << endl;}
};

int main()
{
const base &r = derived();
(void) r; // Suppress compiler warning about unused var.
}
Jul 22 '05 #1
9 1460
"Dave" <be***********@yahoo.com> wrote...

What is the expected output of this program and why???

#include <iostream>

using namespace std;

class base
{
public:
~base() {cout << "base" << endl;}
};

class derived: public base
{
public:
~derived() {cout << "derived" << endl;}
};

int main()
{
const base &r = derived();
(void) r; // Suppress compiler warning about unused var.
}


The output should be

derived
base

After 'main' function finishes and 'r' goes out of scope.

Regarding the subject of your post: there is no polymorphic
behaviour here. A temporary of type 'derived' is created and
later destroyed when a constant reference (bound to its base
class subobject) ceases to exist (see 12.2/5).

Victor
Jul 22 '05 #2

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:VLmGb.470930$275.1368307@attbi_s53...
"Dave" <be***********@yahoo.com> wrote...

What is the expected output of this program and why???

#include <iostream>

using namespace std;

class base
{
public:
~base() {cout << "base" << endl;}
};

class derived: public base
{
public:
~derived() {cout << "derived" << endl;}
};

int main()
{
const base &r = derived();
(void) r; // Suppress compiler warning about unused var.
}


The output should be

derived
base

After 'main' function finishes and 'r' goes out of scope.

Regarding the subject of your post: there is no polymorphic
behaviour here. A temporary of type 'derived' is created and
later destroyed when a constant reference (bound to its base
class subobject) ceases to exist (see 12.2/5).

Victor


This program would have undefined behavior if I had used a pointer rather
than a reference. I'm trying to understand the underlying language
mechanism that makes this case different, but I'm not sure that there is a
really satisfying answer; the answer may be "it just is"...
Jul 22 '05 #3
"Dave" <be***********@yahoo.com> wrote...

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:VLmGb.470930$275.1368307@attbi_s53...
"Dave" <be***********@yahoo.com> wrote...

What is the expected output of this program and why???

#include <iostream>

using namespace std;

class base
{
public:
~base() {cout << "base" << endl;}
};

class derived: public base
{
public:
~derived() {cout << "derived" << endl;}
};

int main()
{
const base &r = derived();
(void) r; // Suppress compiler warning about unused var.
}
The output should be

derived
base

After 'main' function finishes and 'r' goes out of scope.

Regarding the subject of your post: there is no polymorphic
behaviour here. A temporary of type 'derived' is created and
later destroyed when a constant reference (bound to its base
class subobject) ceases to exist (see 12.2/5).

Victor


This program would have undefined behavior if I had used a pointer rather
than a reference.


It would be a different program.
I'm trying to understand the underlying language
mechanism that makes this case different, but I'm not sure that there is a
really satisfying answer; the answer may be "it just is"...


If a reference (a const one) is bound to a temporary, the lifetime of
the temporary extends to match the lifetime of the reference. It is
mandated by the Standard, and I've given you the subclause/paragraph
number. What else mechanism you're talking about, I am not sure.

Victor
Jul 22 '05 #4

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:v2oGb.449122$Dw6.1358306@attbi_s02...
"Dave" <be***********@yahoo.com> wrote...

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:VLmGb.470930$275.1368307@attbi_s53...
"Dave" <be***********@yahoo.com> wrote...
>
> What is the expected output of this program and why???
>
>
>
> #include <iostream>
>
> using namespace std;
>
> class base
> {
> public:
> ~base() {cout << "base" << endl;}
> };
>
> class derived: public base
> {
> public:
> ~derived() {cout << "derived" << endl;}
> };
>
> int main()
> {
> const base &r = derived();
> (void) r; // Suppress compiler warning about unused var.
> }

The output should be

derived
base

After 'main' function finishes and 'r' goes out of scope.

Regarding the subject of your post: there is no polymorphic
behaviour here. A temporary of type 'derived' is created and
later destroyed when a constant reference (bound to its base
class subobject) ceases to exist (see 12.2/5).

Victor


This program would have undefined behavior if I had used a pointer rather than a reference.


It would be a different program.
I'm trying to understand the underlying language
mechanism that makes this case different, but I'm not sure that there is a really satisfying answer; the answer may be "it just is"...


If a reference (a const one) is bound to a temporary, the lifetime of
the temporary extends to match the lifetime of the reference. It is
mandated by the Standard, and I've given you the subclause/paragraph
number. What else mechanism you're talking about, I am not sure.

Victor


But how is the proper destructor execution sequence occurring given that we
have a const reference to *base*? What causes the *derived* destructor to
be executed? Why would it be executed given that nothing polymorphic is
going on?

Also, the output I actually see is:

derived
base
derived
base

This I don't understand. I would have expected exactly the output you
predicted!

Another interesting point: Suppose I change the definition of r to the
following:

const base &r(derived());

In this case, I get no output at all!

Not sure what's going on with all of this...
Jul 22 '05 #5
Not sure why you are getting the repeats. I don't get them here.
I am using g++. Maybe it is a compiler issue.

On Wed, 24 Dec 2003 15:45:47 -0700, Dave wrote:

"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:v2oGb.449122$Dw6.1358306@attbi_s02...
"Dave" <be***********@yahoo.com> wrote...
>
> "Victor Bazarov" <v.********@comAcast.net> wrote in message
> news:VLmGb.470930$275.1368307@attbi_s53...
> > "Dave" <be***********@yahoo.com> wrote...
> > >
> > > What is the expected output of this program and why???
> > >
> > >
> > >
> > > #include <iostream>
> > >
> > > using namespace std;
> > >
> > > class base
> > > {
> > > public:
> > > ~base() {cout << "base" << endl;}
> > > };
> > >
> > > class derived: public base
> > > {
> > > public:
> > > ~derived() {cout << "derived" << endl;}
> > > };
> > >
> > > int main()
> > > {
> > > const base &r = derived();
> > > (void) r; // Suppress compiler warning about unused var.
> > > }
> >
> > The output should be
> >
> > derived
> > base
> >
> > After 'main' function finishes and 'r' goes out of scope.
> >
> > Regarding the subject of your post: there is no polymorphic
> > behaviour here. A temporary of type 'derived' is created and
> > later destroyed when a constant reference (bound to its base
> > class subobject) ceases to exist (see 12.2/5).
> >
> > Victor
> >
> >
>
> This program would have undefined behavior if I had used a pointer rather > than a reference.


It would be a different program.
> I'm trying to understand the underlying language
> mechanism that makes this case different, but I'm not sure that there is a > really satisfying answer; the answer may be "it just is"...


If a reference (a const one) is bound to a temporary, the lifetime of
the temporary extends to match the lifetime of the reference. It is
mandated by the Standard, and I've given you the subclause/paragraph
number. What else mechanism you're talking about, I am not sure.

Victor


But how is the proper destructor execution sequence occurring given that we
have a const reference to *base*? What causes the *derived* destructor to
be executed? Why would it be executed given that nothing polymorphic is
going on?

Also, the output I actually see is:

derived
base
derived
base

This I don't understand. I would have expected exactly the output you
predicted!

Another interesting point: Suppose I change the definition of r to the
following:

const base &r(derived());

In this case, I get no output at all!

Not sure what's going on with all of this...


Jul 22 '05 #6
"Dave" <be***********@yahoo.com> wrote in message
news:vu***********@news.supernews.com

But how is the proper destructor execution sequence occurring given
that we have a const reference to *base*? What causes the *derived*
destructor to be executed? Why would it be executed given that
nothing polymorphic is going on?

I don't know the answer, but this is my guess. Suppose that you simply
entered

Derived();

Then the destructor for the derived class will be called, courtesy of the
mechanism for handling temporaries. I suspect that it is this same mechanism
that is being used when you assign the temporary to a const reference to a
base object. The only effect of the const reference is to defer the
destruction of the temporary; the basic mechanism of destruction is the same
as if no assignment had been made.
Also, the output I actually see is:

derived
base
derived
base

This I don't understand. I would have expected exactly the output you
predicted!


I suspect a bug. With VC++2002, I get the same repeated output as you do.
If, however, I add a constructor, then the output is as expected.

class base
{
public:
base() {cout << "base constructor" << endl;}
~base() {cout << "base destructor" << endl;}
};

class derived: public base
{
public:
derived() {cout << "derived constructor" << endl;}
~derived() {cout << "derived destructor" << endl;}
};
--
John Carson
1. To reply to email address, remove donald
2. Don't reply to email address (post here instead)

Jul 22 '05 #7
"Dave" <be***********@yahoo.com> wrote...
[...]

Another interesting point: Suppose I change the definition of r to the
following:

const base &r(derived());

In this case, I get no output at all!

Not sure what's going on with all of this...

const base& r(derived());

is a declaration of a function 'r' that takes one argument of type
'derived' and returns a reference to const base. Internal parens
do not matter.

Victor
Jul 22 '05 #8
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:U_DGb.39324$VB2.79533@attbi_s51
"Dave" <be***********@yahoo.com> wrote...
[...]

Another interesting point: Suppose I change the definition of r to
the following:

const base &r(derived());

In this case, I get no output at all!

Not sure what's going on with all of this...

const base& r(derived());

is a declaration of a function 'r' that takes one argument of type
'derived' and returns a reference to const base. Internal parens
do not matter.

Victor


VC++ 2002 doesn't interpret it that way (it treats it as an assignment to r)
but I presume that this is just a bug.

Comeau online, by contrast, does treat it as a function declaration, but
interprets the function's parameter as a pointer to a function that takes no
parameters and returns a derived object. Thus the following compiles:

derived foo()
{
derived d;
return d;
}

int main()
{
const base &r(derived());
r(foo);
}
whereas the following fails with the error message:

error: no suitable conversion function from "derived" to
"derived (*)()" exists
int main()
{
const base &r(derived());
derived dobject;
r(dobject);
}

I don't know if this is a bug or if there is some way in which a parameter
of type

derived()

can legitimately be intepreted as a parameter of type

derived(*)().

--
John Carson
1. To reply to email address, remove donald
2. Don't reply to email address (post here instead)

Jul 22 '05 #9
"John Carson" <do***********@datafast.net.au> wrote...
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:U_DGb.39324$VB2.79533@attbi_s51
"Dave" <be***********@yahoo.com> wrote...
[...]

Another interesting point: Suppose I change the definition of r to
the following:

const base &r(derived());

In this case, I get no output at all!

Not sure what's going on with all of this...

const base& r(derived());

is a declaration of a function 'r' that takes one argument of type
'derived' and returns a reference to const base. Internal parens
do not matter.

Victor


VC++ 2002 doesn't interpret it that way (it treats it as an assignment to

r) but I presume that this is just a bug.

Comeau online, by contrast, does treat it as a function declaration, but
interprets the function's parameter as a pointer to a function that takes no parameters and returns a derived object.
Yes, that's probably more correct, I've confused it with a situation

someothertype a;
const base& r(derived(a));

where the second 'a' is not an argument to a function-style cast, but
rather a [superfluous] name of an argument in a function declaration.
Thus the following compiles:

derived foo()
{
derived d;
return d;
}

int main()
{
const base &r(derived());
r(foo);
}
whereas the following fails with the error message:

error: no suitable conversion function from "derived" to
"derived (*)()" exists
int main()
{
const base &r(derived());
derived dobject;
r(dobject);
}

I don't know if this is a bug or if there is some way in which a parameter
of type

derived()

can legitimately be intepreted as a parameter of type

derived(*)().


I can't find any support for that in the Standard. It, apparently,
allows an argument to a function to be another function, and there
is no conversion necessary, AFAICT.

If 'T' is a function, an lvalue of type T can be converted to an rvalue
of type "a pointer to T", which will be "a pointer to a function ...".
However, there is nothing in the Standard that says that in a function
declaration a declaration of an argument in case of a function shall be
interpreted as a pointer to a function.

Victor
Jul 22 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Dave Theese | last post by:
Please consider this code: class base {}; class derived: public base {}; base *ptr = new derived; cout << typeid(*base).name << endl; In this case, I see output of "class base" rather than...
5
by: S. Levent Yilmaz | last post by:
Is it possible to have the constructor in an interface call member functions polymorphically? For instance: ============================== // INTERFACE CLASS class SomeInterface { public:...
2
by: Aryeh M. Friedman | last post by:
If I have something like this: class NumberException { }; class Number { public: ... virtual unsigned long getValue() {throw(NumberException);}; ...
20
by: verec | last post by:
One problem I've come accross in designing a specific version of auto_ptr is that I have to disntiguish between "polymorphic" arguments and "plain" ones, because the template has to, internally,...
9
by: Karel Miklav | last post by:
In lots of places in a programm I need to identify type of received messages, so I create them as virtual classes and use RTTI to find their type later. But these are simple messages, often without...
7
by: Peter Oliphant | last post by:
I use to make the statement that you could always replace any 'private' or 'public' access with 'public' and the code would still compile. This is no longer the case. It turns out that in /clr...
12
by: Bob | last post by:
Hi, 'Shadowed' properties are not polymorphic. (See thread 'Inheritance and late binding') They should be. Problem: Base class has read only property 'X'. Derived class must have read / write...
5
by: Ben Pope | last post by:
Hi all, This is not something I've played around with much, but I'm designing some factories and I want a function like this: template<class T> T* Creator() { return new T; }
7
by: Arindam | last post by:
#include <cstdio> struct Test { void bar() { foo(); } private: virtual void foo() { printf("Test\n"); }
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
3
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
2
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.