Topic: Calling pure virtual functions from an abstract class constructor or destructor.
Author: spam@spamguard.com ("Gene Bushuyev")
Date: Sun, 20 Nov 2005 15:49:29 GMT Raw View
"Richard Corden" <richard_corden@hotmail.com> wrote in message
news:437E779E.7010401@hotmail.com...
[...]
Your example doesn't reflect what the standard describes in 10.4/6
> I believe my confusion is with what 'object' means in 10.4/6. I couldn't find
> a definition for 'object'. One of the few places is 1.8/2
The definition of the object? - The one that is being constructed (destroyed.)
The paragraph speaks about construction or destruction.
> which actually says that an object can contain other objects, ie. sub objects
> and base class subobjects.
>
> I just wanted to make sure that there wasn't a legitimate implementation
> reason why pure virtuals would require different handling.
What do you mean by "different handling?" All the paragraph says is that calling
a pure virtual function from an abstract base constructor (destructor) is
undefined. Which is an obvious behavior as the dynamic type of the object is
adjusted in the constructor to its static type, so calling a virtual function is
always non-virtual. If such a function is abstract, the behavior is undefined
(usually a crash).
For example,
struct A
{
virtual void f() = 0;
A()
{
f(); // undefined 10.4/6
}
};
struct B : A
{
virtual void f() {}
B() : A
{
f(); // this is ok
}
}
-- Gene Bushuyev
----------------------------------------------------------------
There is no greatness where there is no simplicity, goodness and truth. ~ Leo
Tolstoy
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kuyper@wizard.net
Date: Sun, 20 Nov 2005 22:21:03 CST Raw View
Richard Corden wrote:
> Gene Bushuyev wrote:
.
> > The definition of the object? - The one that is being constructed (destroyed.)
> > The paragraph speaks about construction or destruction.
>
> 10.4/6 uses the phrase 'object being created'. This text is also used
> in 5.3.4/10 where it says the argument to 'operator new' shall be no
> less than the size of the 'object being created'. In that context this
> would include base class subobjects.
No - not in the sense that you mean. Inside the constructor of a
derived class, construction of the base class is already complete; it's
only the derived object which is still being constructed. That being
the case, calling a base class pure virtual function which is defined
in the derived class is perfect legal; it calls the version defined for
that derived class.
> >>I just wanted to make sure that there wasn't a legitimate implementation
> >>reason why pure virtuals would require different handling.
> >
> >
> > What do you mean by "different handling?" All the paragraph says is that calling
> > a pure virtual function from an abstract base constructor (destructor) is
> > undefined. Which is an obvious behavior as the dynamic type of the object is
> > adjusted in the constructor to its static type, so calling a virtual function is
> > always non-virtual.
>
> Are you using an analogy here or does the standard explicitly specify
> that?
Yes, the standard is pretty specific about when precisely an object
becomes an object of the derived type, and it's just as specific about
when it ceases to become an object of that type. This corresponds to
the point at which, in a typical implementation, the virtual function
table pointer is changed.
> struct A
> {
> virtual void f() = 0;
> virtual void b() = 0;
> };
>
> struct B : A
> {
> virtual void f() {}
> B() : A()
> {
> f(); // (1)
> b(); // (2)
> }
> }
>
> IMHO, (1) is identical to (2) with respect 10.4/6.
No. During the construction of B, the object is of type B, and the
virtual call to f() results in a call to B::f(). A definition of B::b()
might be provided in a derived class, but that doesn't help, because at
the time of the call to the constructor of B, the object isn't yet of
the derived class. Therefore the only definition of b() that could be
used is one provided in B or it's base classes - and there is no such
definition.
> I have come up with two possible interpretations of 10.6/4:
.
> b) The standard wants to be more flexible, ie. 'In the constructor or
> destructor for an abstract class, calling a pure virtual function whose
> final overrider is still pure virtual is undefined'.
>
> If I understand you correctly, I believe you feel the standard implies
> option 'b'.
That's correct.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alfps@start.no (Alf P. Steinbach)
Date: Sun, 20 Nov 2005 22:48:22 CST Raw View
* Richard Corden:
>
> struct A
> {
> virtual void f() = 0;
> virtual void b() = 0;
> };
>
> struct B : A
> {
> virtual void f() {}
> B() : A()
> {
> f(); // (1)
> b(); // (2)
> }
> }
>
> IMHO, (1) is identical to (2) with respect 10.4/6.
>
> I have come up with two possible interpretations of 10.6/4:
>
> a) The standard does wish to forbid both (1) and (2), ie. 'In the
> constructor or destructor for an abstract class, calling a pure virtual
> function that is a member of the class or a base class is undefined'.
In your example (2) is not pure virtual.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: alfps@start.no (Alf P. Steinbach)
Date: Mon, 21 Nov 2005 05:25:44 GMT Raw View
* Alf P. Steinbach:
> >
> > struct A
> > {
> > virtual void f() = 0;
> > virtual void b() = 0;
> > };
> >
> > struct B : A
> > {
> > virtual void f() {}
> > B() : A()
> > {
> > f(); // (1)
> > b(); // (2)
> > }
> > }
>
> In your example (2) is not pure virtual.
Moderator, please, the next time my computer transposes two bits at the
end of a byte -- as it does all the time -- can't you just fix it?
I meant (1), that's call number (one), ("o", "n", "e"), (uno), (en),
roman literal (i), is not a call of a pure virtual function.
Hope that redundance will be more than my computer's change-the-meaning
circuit can handle...
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: johnchx2@yahoo.com
Date: Tue, 22 Nov 2005 19:54:30 CST Raw View
Richard Corden wrote:
> Alf P. Steinbach wrote:
>
> [In your example (1) is not pure virtual.]
>
>
> I have not been able to find any text which says that if 'f' has a non
> pure virtual final overrider it ceases to be 'pure virtual'.
I think the key is that there is no function 'f()'. There is A::f()
and B::f(). A::f() is, and ever shall be, pure virtual. B::f() is not
now, nor ever has been, pure virtual.
The member name lookup rules (*not* virtual function dispatch) specify
that the expression f() in B::B() resolves to B::f().
The same member name lookup rules say that b() in B::B() resolves to
A::b(), which is pure virtual, making the effect of the call undefined.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: johnchx2@yahoo.com
Date: Wed, 23 Nov 2005 22:45:06 CST Raw View
Richard Corden wrote:
> johnchx2@yahoo.com wrote:
> > I think the key is that there is no function 'f()'. There is A::f()
> > and B::f(). A::f() is, and ever shall be, pure virtual. B::f() is not
> > now, nor ever has been, pure virtual.
> >
> > The member name lookup rules (*not* virtual function dispatch) specify
> > that the expression f() in B::B() resolves to B::f().
>
> Excellent!! This is the section I am missing.
>
> However, I was unable to find where this is stated, can you show me
> where this is stated?
Member name lookup is described in 10.2. In particular, 10.2/2
specifies that the name declared in the derived class hides the member
name declared in the base class. 3.3.7/3 says the same thing.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]