Re: derived class and virtual function
* James Kanze, on 18.08.2010 11:52:
On Aug 18, 1:21 am, "Alf P. Steinbach /Usenet"<alf.p.steinbach
+use...@gmail.com> wrote:
* ?? Tiib, on 18.08.2010 02:13:
On 18 aug, 02:54, red floyd<no.spam.h...@its.invalid> wrote:
On 8/17/2010 1:54 AM, James Kanze wrote:
On Aug 13, 10:09 am, "Francesco S. Carta"<entul...@gmail.com> 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>