473,397 Members | 1,972 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,397 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 1477
"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: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

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.