Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > derived class and virtual function

Reply
Thread Tools

derived class and virtual function

 
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      08-18-2010
* Öö Tiib, on 18.08.2010 02:13:
> On 18 aug, 02:54, red floyd<(E-Mail Removed)> wrote:
>> On 8/17/2010 1:54 AM, James Kanze wrote:
>>> On Aug 13, 10:09 am, "Francesco S. Carta"<(E-Mail Removed)> wrote:
>> >
>>>> #include<iostream>
>>>>
>>>> using namespace std;
>>>>
>>>> class Base {
>>>> public:
>>>> Base(int data = 0) : data(data) {};
>>>> Base(const Base& base) : data(base.data) {};
>>>> virtual Base* Clone() const {
>>>> cout<< "cloning Base"<< endl;
>>>> return new Base(*this);
>>>> }
>>>> int Data() const {
>>>> return data;
>>>> }
>>>> private:
>>>> int data;
>>>> };
>>>>
>>>> class Derived : private Base {
>>>> public:
>>>> Derived(int data = 0) : Base(data) {};
>>>> Derived(const Derived& derived) : Base(derived) {};
>>>> Base* Clone() const {
>>>
>>> Here, you're still returning a Base. Any conversion takes place
>>> in Derived (where the derivation is visible).
>> >
>>> Try changing the return type to Derived*; the compiler should
>>> complain then.
>>>
>>> See §10.3/5 in the standard for details.

>>
>> James, I thought that the compiler should *not* complain if the
>> return type of Derived::Clone was Derived*. Isn't that a
>> covariant return type?

>
> Did you eyeball §10.3/5? Base is not accessible base class of Derived
> so it is not a covariant there by standard.


Base is accessible /in/ D.

That makes the function covariant per §10.3/5.

Not sure what the discussion otherwise is about, so I can't comment on what
James meant -- possibly referring to some other invoking code.


Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
 
 
 
Öö Tiib
Guest
Posts: n/a
 
      08-18-2010
On 18 aug, 03:21, "Alf P. Steinbach /Usenet" <alf.p.steinbach
(E-Mail Removed)> wrote:
> * Öö Tiib, on 18.08.2010 02:13:
>
>
>
> > On 18 aug, 02:54, red floyd<(E-Mail Removed)> *wrote:
> >> On 8/17/2010 1:54 AM, James Kanze wrote:
> >>> On Aug 13, 10:09 am, "Francesco S. Carta"<(E-Mail Removed)> * *wrote:

>
> >>>> #include<iostream>

>
> >>>> using namespace std;

>
> >>>> class Base {
> >>>> * * * *public:
> >>>> * * * *Base(int data = 0) : data(data) {};
> >>>> * * * *Base(const Base& * *base) : data(base.data) {};
> >>>> * * * *virtual Base* Clone() const {
> >>>> * * * * * *cout<< * *"cloning Base"<< * *endl;
> >>>> * * * * * *return new Base(*this);
> >>>> * * * *}
> >>>> * * * *int Data() const {
> >>>> * * * * * *return data;
> >>>> * * * *}
> >>>> * * * *private:
> >>>> * * * *int data;
> >>>> };

>
> >>>> class Derived : private Base {
> >>>> * * * *public:
> >>>> * * * *Derived(int data = 0) : Base(data) {};
> >>>> * * * *Derived(const Derived& * *derived) : Base(derived) {};
> >>>> * * * *Base* Clone() const {

>
> >>> Here, you're still returning a Base. *Any conversion takes place
> >>> in Derived (where the derivation is visible).

>
> >>> Try changing the return type to Derived*; the compiler should
> >>> complain then.

>
> >>> See §10.3/5 in the standard for details.

>
> >> James, I thought that the compiler should *not* complain if the
> >> return type of Derived::Clone was Derived*. *Isn't that a
> >> covariant return type?

>
> > Did you eyeball §10.3/5? Base is not accessible base class of Derived
> > so it is not a covariant there by standard.

>
> Base is accessible /in/ D.
>
> That makes the function covariant per §10.3/5.
>
> Not sure what the discussion otherwise is about, so I can't comment on what
> James meant *-- *possibly referring to some other invoking code.


Oh yes ... Base is accessible in Derived, since it is its own base
class. My bad, time to go sleep perhaps. <g>
 
Reply With Quote
 
 
 
 
James Kanze
Guest
Posts: n/a
 
      08-18-2010
On Aug 18, 1:21 am, "Alf P. Steinbach /Usenet" <alf.p.steinbach
(E-Mail Removed)> wrote:
> * Öö Tiib, on 18.08.2010 02:13:
> > On 18 aug, 02:54, red floyd<(E-Mail Removed)> wrote:
> >> On 8/17/2010 1:54 AM, James Kanze wrote:
> >>> On Aug 13, 10:09 am, "Francesco S. Carta"<(E-Mail Removed)> wrote:


> >>>> #include<iostream>


> >>>> using namespace std;


> >>>> class Base {
> >>>> public:
> >>>> Base(int data = 0) : data(data) {};
> >>>> Base(const Base& base) : data(base.data) {};
> >>>> virtual Base* Clone() const {
> >>>> cout<< "cloning Base"<< endl;
> >>>> return new Base(*this);
> >>>> }
> >>>> int Data() const {
> >>>> return data;
> >>>> }
> >>>> private:
> >>>> int data;
> >>>> };


> >>>> class Derived : private Base {
> >>>> public:
> >>>> Derived(int data = 0) : Base(data) {};
> >>>> Derived(const Derived& derived) : Base(derived) {};
> >>>> Base* Clone() const {


> >>> Here, you're still returning a Base. Any conversion takes place
> >>> in Derived (where the derivation is visible).


> >>> Try changing the return type to Derived*; the compiler should
> >>> complain then.


> >>> See §10.3/5 in the standard for details.


> >> James, I thought that the compiler should *not* complain if the
> >> return type of Derived::Clone was Derived*. Isn't that a
> >> covariant return type?


> > Did you eyeball §10.3/5? Base is not accessible base class
> > of Derived so it is not a covariant there by standard.


> Base is accessible /in/ D.


But not generally.

> That makes the function covariant per §10.3/5.


§10.3/5 doesn't say "accessible in D" (at least not in C++03);
it just says "accessible". Without saying where, but since the
original language said "accessible in D", and this was changed,
we have to assume that it means "generally accessible", or
something like that. Which is, of course, the most logical
interpretation, because the actual conversion takes place after
the return, outside of D.

On the other hand, the example at the end of §10.3/5 does
suggest that accessibility is checked in the context of D.
(Examples are non-normative, but they do indicate intent.) So
maybe the question should be raised in comp.std.c++.

--
James Kanze
 
Reply With Quote
 
subramanian100in@yahoo.com, India
Guest
Posts: n/a
 
      08-18-2010
* On Aug 17, 1:48 pm, James Kanze <(E-Mail Removed)> wrote:
> On Aug 13, 9:39 am, "Francesco S. Carta" <(E-Mail Removed)> wrote:
>
> > (E-Mail Removed), India <(E-Mail Removed)>, on
> > 13/08/2010 01:29:13, wrote:


> I don't think that's what is meant (although it's hard to
> say---the sentence is unclear, at least without its surrounding

^^^^^^^^^^^
> context).

^^^^^^^
[...]
> James Kanze


Here I write down the complete paragraph; perhaps that will be useful
in explaining the last sentence.

In Stanley Lippman's 'C++ Primer Fourth Edition', in page 564, the
following is mentioned:

"With one exception, the declaration of a virtual function in the
derived class must exactly match the way the function is defined in
the base. That exception applies to virtuals that return a
reference(or pointer) to a type that is itself a base class. A virtual
function in the derived class can return a reference or pointer to a
class that is PUBLICLY derived from the type returned by the base
class function."

I have written the follwing program a.cpp after going through one of
Stuart Redmann's replies in this thread:

#include <cstdlib>
#include <iostream>

using namespace std;

class X
{
public:
void print(void) const;
};

inline void X:rint(void) const
{
cout << "from X:rint() function" << endl;

return;
}

class Y : public X
{
public:
void print(void) const;
};

inline void Y:rint(void) const
{
cout << "from Y:rint() function" << endl;

return;
}

class Base
{
public:
virtual X* get(X& x) const;
virtual ~Base();
};

inline X* Base::get(X& x) const
{
cout << "Base::get() called" << endl;

return &x;
}

inline Base::~Base()
{
}

class Derived : public Base
{
public:
virtual Y* get(Y& y) const;
virtual ~Derived();
};

inline Y* Derived::get(Y& y) const
{
cout << "Derived::get() called" << endl;

return &y;
}

inline Derived::~Derived()
{
}

int main()
{
X x;
Y y;
Derived* pd = new Derived();
Y* py = pd->get(y);
py->print();
delete pd;
pd = 0;
Base* pb = new Base();
X* px = pb->get(x);
px->print();
delete pb;
pb = 0;

return EXIT_SUCCESS;
}

This program compiles fine with g++ and produces the output:

Derived::get() called
from Y:rint() function
Base::get() called
from X:rint() function

Does the above program correctly demonstrate what is mentioned in the
paragraph(in Stanley Lippman's book - page 564) that I had mentioned
completely above? Kindly reply. If I am wrong in understanding that
paragraph, please explain it.

Thanks
V.Subramanian

 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      08-18-2010
* James Kanze, on 18.08.2010 11:52:
> On Aug 18, 1:21 am, "Alf P. Steinbach /Usenet"<alf.p.steinbach
> (E-Mail Removed)> wrote:
>> * Öö Tiib, on 18.08.2010 02:13:
>>> On 18 aug, 02:54, red floyd<(E-Mail Removed)> wrote:
>>>> On 8/17/2010 1:54 AM, James Kanze wrote:
>>>>> On Aug 13, 10:09 am, "Francesco S. Carta"<(E-Mail Removed)> wrote:

>
>>>>>> #include<iostream>

>
>>>>>> using namespace std;

>
>>>>>> class Base {
>>>>>> public:
>>>>>> Base(int data = 0) : data(data) {};
>>>>>> Base(const Base& base) : data(base.data) {};
>>>>>> virtual Base* Clone() const {
>>>>>> cout<< "cloning Base"<< endl;
>>>>>> return new Base(*this);
>>>>>> }
>>>>>> int Data() const {
>>>>>> return data;
>>>>>> }
>>>>>> private:
>>>>>> int data;
>>>>>> };

>
>>>>>> class Derived : private Base {
>>>>>> public:
>>>>>> Derived(int data = 0) : Base(data) {};
>>>>>> Derived(const Derived& derived) : Base(derived) {};
>>>>>> Base* Clone() const {

>
>>>>> Here, you're still returning a Base. Any conversion takes place
>>>>> in Derived (where the derivation is visible).

>
>>>>> Try changing the return type to Derived*; the compiler should
>>>>> complain then.

>
>>>>> See §10.3/5 in the standard for details.

>
>>>> James, I thought that the compiler should *not* complain if the
>>>> return type of Derived::Clone was Derived*. Isn't that a
>>>> covariant return type?

>
>>> Did you eyeball §10.3/5? Base is not accessible base class
>>> of Derived so it is not a covariant there by standard.

>
>> Base is accessible /in/ D.

>
> But not generally.
>
>> That makes the function covariant per §10.3/5.

>
> §10.3/5 doesn't say "accessible in D" (at least not in C++03);
> it just says "accessible". Without saying where, but since the
> original language said "accessible in D", and this was changed,
> we have to assume that it means "generally accessible", or
> something like that.


No.

It's most likely just an editoral change done during changes to support
covariance with rvalue references.

With the "generally accessible" interpretation the new wording would break
existing code, and it would be the first place ever that the standard restricted
what you could do because of inaccessibility from other places.


> Which is, of course, the most logical
> interpretation, because the actual conversion takes place after
> the return, outside of D.


No. Where it does take place outside of D code it needs not be a conversion at
the source code level. That is, at the call site the class D can be totally
absent from the picture -- that's the point of a 'clone' op, after all.

The following compiles fine with Comeau Online (C++0x enabled), g++ 4.4.1 (both
as C++98 and C++0x) and Visual C++ 10.0 (which has some C++0x features):


<code>
#include <iostream>

class Base
{
public:
virtual Base* clone()
{
std::cout << "Base::clone" << std::endl;
return new Base( *this );
}
};

class Derived
: private Base
{
public:
Base& asBase() { return *this; }
virtual Derived* clone()
{
std::cout << "Derived::clone" << std::endl;
return new Derived( *this );
}
};

int main()
{
Derived o;
Base& r = o.asBase();
Base* p = r.clone();
}
</code>


So in conclusion your interpretation of the changed C++0x wording does not
correspond to how current compilers do things.

And Stanley Lippman's explanation, cited else-thread by "subramanian", and
requiring above program to fail compilation, is also dead wrong with respect to
C++98 standard and with respect to actual compilers.


> On the other hand, the example at the end of §10.3/5 does
> suggest that accessibility is checked in the context of D.
> (Examples are non-normative, but they do indicate intent.) So
> maybe the question should be raised in comp.std.c++.


Perhaps. I have no problem with the current wording. I don't know of any
instances where the standard uses "accessible" to mean "accessible from
else-where" -- it always means "accessible at this point".


Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Casting a pointer to virtual member function from derived class tobase class Alex Shen C++ 5 10-30-2010 01:03 AM
Why polymorph fails when virtual function is decleared private in base class and public in derived class? Fred C++ 2 06-03-2007 02:59 PM
Derived::Derived(const Base&) and Derived& operator=(const Base&) developereo@hotmail.com C++ 1 05-23-2007 01:44 PM
Derived::Derived(const Base&) and Derived& operator=(const Base&) developereo@hotmail.com C++ 1 05-23-2007 12:07 AM
What will happen if a virtual function is declared to be virtual again in a derived class? Xiangliang Meng C++ 2 06-21-2004 03:14 AM



Advertisments