By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,171 Members | 992 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,171 IT Pros & Developers. It's quick & easy.

pure virttual function

P: n/a
sks

Hi ,
could anyone explain me why definition to a pure virtual function
is allowed ?

Jul 5 '06 #1
Share this Question
Share on Google+
21 Replies


P: n/a

sks wrote:
Hi ,
could anyone explain me why definition to a pure virtual function
is allowed ?
May be you are asking why it is not allowed.

See FAQ. it is better explained there.

http://www.parashift.com/c++-faq-lite/

-- Murali Krishna

Jul 5 '06 #2

P: n/a
"sks" <es******@gmail.comwrote in message
news:11**********************@l70g2000cwa.googlegr oups.com...
>
Hi ,
could anyone explain me why definition to a pure virtual function
is allowed ?
Yes, Herb Sutter can:

http://www.gotw.ca/gotw/031.htm

Hope this helps :)
Stu
Jul 5 '06 #3

P: n/a
sks
Murali Krishna wrote:
sks wrote:
Hi ,
could anyone explain me why definition to a pure virtual function
is allowed ?

May be you are asking why it is not allowed.

See FAQ. it is better explained there.

http://www.parashift.com/c++-faq-lite/

-- Murali Krishna
No , My question was why defintion to pure virtual is allowed in the
base class eg this way

class ABC
{
public:
virtual f1()=0;
{
std::cout<<"Hi";
}
}

You may derive this class and provide your own implementation to f1()
but what is the use in allowing the definition in base class?

Jul 5 '06 #4

P: n/a
* Murali Krishna:
*sks:
>could anyone explain me why definition to a pure virtual function
is allowed ?

May be you are asking why it is not allowed.
Sorry, the OP is correct that you can provide a definition for a pure
virtual function. But that definition can't be provided in the class
definition. As to the why of that, I don't know any good reason, and
that's better asked in [comp.std.c++].

One use for a defined pure virtual function is a "marker interface" like

struct Serializable
{
inline virtual ~Serializable() = 0;
};

inline Serializable::~Serializable() {}

Here a definition is necessary because the destructor will be called
(although it's never called virtually), and the destructor is the only
member function that for this class can be used to make it abstract.

--
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?
Jul 5 '06 #5

P: n/a
TB
Murali Krishna skrev:
sks wrote:
>Hi ,
could anyone explain me why definition to a pure virtual function
is allowed ?

May be you are asking why it is not allowed.
No he isn't.

class A {
public:
virtual void foo() = 0;
};

void A::foo() { }

class C : public A {
public:
void foo() {
A::foo();
}
};

int main(int argc, char* argv[])
{
C c;
c.foo();
return 0;
}
--
TB @ SWEDEN
Jul 5 '06 #6

P: n/a
sks

Stuart Golodetz wrote:
"sks" <es******@gmail.comwrote in message
news:11**********************@l70g2000cwa.googlegr oups.com...

Hi ,
could anyone explain me why definition to a pure virtual function
is allowed ?

Yes, Herb Sutter can:

http://www.gotw.ca/gotw/031.htm

Hope this helps :)
Stu
Thanks stuart . I have got answers to the question .

Jul 5 '06 #7

P: n/a
* Stuart Golodetz:
"sks" <es******@gmail.comwrote in message
news:11**********************@l70g2000cwa.googlegr oups.com...
>Hi ,
could anyone explain me why definition to a pure virtual function
is allowed ?

Yes, Herb Sutter can:

http://www.gotw.ca/gotw/031.htm

Hope this helps :)
Unfortunately reason #3 in that text is, if not exactly bu*****t, not
something one can rely on, and is with most compiler a technique that
/does not work/. Where it works -- if such a compiler exists nowadays
-- it's because Undefined Behavior can be anything, including that a
virtual call to a pure virtual function might end up in that pure
virtual function's definition. But if I could (unfortunately I can't)
I'd light a huge bonfire and throw that advice on top.

--
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?
Jul 5 '06 #8

P: n/a
"Alf P. Steinbach" <al***@start.nowrote in message
news:4h*************@individual.net...
>* Stuart Golodetz:
>"sks" <es******@gmail.comwrote in message
news:11**********************@l70g2000cwa.googleg roups.com...
>>Hi ,
could anyone explain me why definition to a pure virtual function
is allowed ?

Yes, Herb Sutter can:

http://www.gotw.ca/gotw/031.htm

Hope this helps :)

Unfortunately reason #3 in that text is, if not exactly bu*****t, not
something one can rely on, and is with most compiler a technique that
/does not work/. Where it works -- if such a compiler exists
nowadays -- it's because Undefined Behavior can be anything, including
that a virtual call to a pure virtual function might end up in that pure
virtual function's definition. But if I could (unfortunately I can't) I'd
light a huge bonfire and throw that advice on top.

--
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?
Hmm, my bad it would seem. Reading it again, I noticed that #2 isn't
entirely right either; it says "B::f(i)" when B::f doesn't take any
parameters. Oh well, it seemed like a good page to direct the OP to at the
time...

Apologies,
Stu
Jul 5 '06 #9

P: n/a
sks wrote:
Murali Krishna wrote:
sks wrote:
Hi ,
could anyone explain me why definition to a pure virtual function
is allowed ?
May be you are asking why it is not allowed.

See FAQ. it is better explained there.

http://www.parashift.com/c++-faq-lite/

-- Murali Krishna

No , My question was why defintion to pure virtual is allowed in the
base class eg this way

class ABC
{
public:
virtual f1()=0;
{
std::cout<<"Hi";
}
}

You may derive this class and provide your own implementation to f1()
but what is the use in allowing the definition in base class?
This is the first time I am seeing this and I could not believe it is
compiling. I don't know when will I open my eyes.

Murali.. come on wakeup!!

thanks for that sks.

-- Murali Krishna

Jul 5 '06 #10

P: n/a
Alf P. Steinbach wrote:
* Murali Krishna:
>*sks:
>>could anyone explain me why definition to a pure virtual function
is allowed ?

May be you are asking why it is not allowed.

Sorry, the OP is correct that you can provide a definition for a pure
virtual function. But that definition can't be provided in the class
definition. As to the why of that, I don't know any good reason, and
that's better asked in [comp.std.c++].

One use for a defined pure virtual function is a "marker interface" like

struct Serializable
{
inline virtual ~Serializable() = 0;
};

inline Serializable::~Serializable() {}

Here a definition is necessary because the destructor will be called
(although it's never called virtually), and the destructor is the only
member function that for this class can be used to make it abstract.
Well, if no polymorphism is needed, but the class shouldn't be
instantiatable, one can always make the destructor protected.

Jul 5 '06 #11

P: n/a
* Rolf Magnus:
Alf P. Steinbach wrote:
>* Murali Krishna:
>>*sks:
could anyone explain me why definition to a pure virtual function
is allowed ?
May be you are asking why it is not allowed.
Sorry, the OP is correct that you can provide a definition for a pure
virtual function. But that definition can't be provided in the class
definition. As to the why of that, I don't know any good reason, and
that's better asked in [comp.std.c++].

One use for a defined pure virtual function is a "marker interface" like

struct Serializable
{
inline virtual ~Serializable() = 0;
};

inline Serializable::~Serializable() {}

Here a definition is necessary because the destructor will be called
(although it's never called virtually), and the destructor is the only
member function that for this class can be used to make it abstract.

Well, if no polymorphism is needed, but the class shouldn't be
instantiatable, one can always make the destructor protected.
Yes, it seems that the practical advantage reduces to the single case of
a polymorphic marker interface through which objects can be deleted, but
heck, there must be more to it for having it as a langugage feature.

--
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?
Jul 5 '06 #12

P: n/a

Alf P. Steinbach wrote:
>
Sorry, the OP is correct that you can provide a definition for a pure
virtual function. But that definition can't be provided in the class
definition. As to the why of that, I don't know any good reason, and
that's better asked in [comp.std.c++].
because the compiler cannot understand the = 0 followed by an opening
brace?

(Maybe too hard for compiler vendors).

Jul 5 '06 #13

P: n/a
Earl Purple wrote:
>
Alf P. Steinbach wrote:
>>
Sorry, the OP is correct that you can provide a definition for a pure
virtual function. But that definition can't be provided in the class
definition. As to the why of that, I don't know any good reason, and
that's better asked in [comp.std.c++].

because the compiler cannot understand the = 0 followed by an opening
brace?
Seems to me rather the other way round. The compiler cannot understand it
because it's not allowed by the C++ grammar.
(Maybe too hard for compiler vendors).
Maybe I'm wrong, but this doesn't really seem to be so problematic.
Considering quite a few other parts of the C++ grammar, this seems trivial.

Jul 5 '06 #14

P: n/a

sks wrote:
Hi ,
could anyone explain me why definition to a pure virtual function
is allowed ?
The easiest to understand is the case for serialization frameworks. If
all classes inherit from a single class, for argument's sake Document
then you will have:

class Document {
public:
void save( ofstream & ) = 0;
void load( ifstream & ) = 0;

std::string author;
};

Derived classes must implement these members and those members must
call the Document member in order that it can save and load the
author's name. Document needs to implement both as well in order to
save and load the author's name.

This is basically an example of the occasion where the sub-class
overrides the virtual to augment the bahaviour of the super class. In
these cases the sub-class must always call the super-class
implementation as they are adding to its behaviour. Even if the upper
level implementations are empty they should still be provided so that
all sub-class implementors know that there is no reason to leave it out
and there will be no link errors when sub-classes call ones that didn't
get implement (probably 'implemented yet').
K

Jul 5 '06 #15

P: n/a
sks wrote:
could anyone explain me why definition to a pure virtual function
is allowed ?
The property of being 'virtual' is not as much the property of the member
function itself, as it is the property of the call method, which will be used
with that function by default in certain cases (see below). There are two
relevant call methods in this case: static (or "non-virtual") and dynamic (or
"virtual").

Dynamic (virtual) call method is used when the function is invoked by
non-qualified name with a pointer or a reference to an object. (This also
includes non-qualified calls to member functions from other member functions.
One can assume that they are implicitly prepended with 'this->...').

For example

struct S { virtual void foo() {} };
...
S s;
S* ps = &s;
S& rs = s;

ps->foo(); // virtual call
rs.foo(); // virtual call

Static (non-virtual) call method is used when the function is invoked: 1) by a
qualified name, 2) with an actual object (not a pointer or reference) 3) when
base class destructor is implicitly called from derived class destructor.

For example

ps->S::foo(); // non-virtual call
s.foo(); // non-virtual call

Now, when you declare some member function as pure virtual, you are effectively
disabling (or should I say "outlawing") the _dynamic_ (virtual) call method.
After that any attempts to invoke the function using a virtual call will lead to
either compiler diagnostic or undefined behavior. However, this has absolutely
no effect on static call methods. These calls remain perfectly valid and they
will go to the function's body (assuming it has one). If you think that it might
be useful in your program to give some member function some static call
functionality while disabling dynamic calls, then you declare it as pure virtual
and at the same time provide a definition (a body) for it.

--
Best regards,
Andrey Tarasevich
Jul 5 '06 #16

P: n/a
* Andrey Tarasevich:
>
Static (non-virtual) call method is used when the function is invoked: 1) by a
qualified name, 2) with an actual object (not a pointer or reference) 3) when
base class destructor is implicitly called from derived class destructor.
Accepting this terminology, point (2) does not apply to a call to a pure
virtual function from a non-static member function of the class (where
you can very easily have UB if that member function is directly or
indirectly called from a constructor of the class), and it does not
apply to a call on a named variable of the class, since no such variable
can exist if the class has a pure virtual function; hence it doesn't
seem to apply to anything in this context, and for the case of a call of
function that's not pure virtual, it's an implementation detail that
only affects the efficiency of a call, if anything, so at the C++ level
it doesn't make much sense to say if that call is virtual or not.

--
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?
Jul 5 '06 #17

P: n/a
Alf P. Steinbach wrote:
>>
Static (non-virtual) call method is used when the function is invoked: 1) by a
qualified name, 2) with an actual object (not a pointer or reference) 3) when
base class destructor is implicitly called from derived class destructor.

Accepting this terminology,
If you are referring to the above use of terms "static" and "dynamic", I agree
that they are a bit ambiguous, since similar terms are used elsewhere in the
language, where they mean something completely different. However, this is not
entirely my invention. This terminology is derived directly from the one used in
the FAQ, see

http://www.parashift.com/c++-faq-lit....html#faq-20.2
http://www.parashift.com/c++-faq-lit....html#faq-20.3
point (2) does not apply to a call to a pure
virtual function from a non-static member function of the class (where
you can very easily have UB if that member function is directly or
indirectly called from a constructor of the class),
I'd say that this is more relevant to point (1), i.e. what I referred to as
"call by a qualified name".
and it does not
apply to a call on a named variable of the class, since no such variable
can exist if the class has a pure virtual function;
That would be point (2), yes.
hence it doesn't
seem to apply to anything in this context, and for the case of a call of
function that's not pure virtual, it's an implementation detail that
only affects the efficiency of a call, if anything, so at the C++ level
it doesn't make much sense to say if that call is virtual or not.
I don't understand what exactly you are referring to by the "implementation
detail" part, since I don't see anything in my post that would be an
implementation detail.

Anyway, my description was not intended to be limited to the particular case of
_pure_ virtual functions. It was supposed to be more generic, with only the last
paragraph of my original message dealing with pure virtual functions in particular.

--
Best regards,
Andrey Tarasevich
Jul 5 '06 #18

P: n/a
sks wrote:
Hi ,
could anyone explain me why definition to a pure virtual function
is allowed ?
See "Effective C++, 3Ed", Item 34 for an example.
Jul 5 '06 #19

P: n/a
* Andrey Tarasevich:
Alf P. Steinbach wrote:
>>Static (non-virtual) call method is used when the function is invoked: 1) by a
qualified name, 2) with an actual object (not a pointer or reference) 3) when
base class destructor is implicitly called from derived class destructor.
Accepting this terminology,

If you are referring to the above use of terms "static" and "dynamic", I agree
that they are a bit ambiguous, since similar terms are used elsewhere in the
language, where they mean something completely different. However, this is not
entirely my invention. This terminology is derived directly from the one used in
the FAQ, see

http://www.parashift.com/c++-faq-lit....html#faq-20.2
http://www.parashift.com/c++-faq-lit....html#faq-20.3
>point (2) does not apply to a call to a pure
virtual function from a non-static member function of the class (where
you can very easily have UB if that member function is directly or
indirectly called from a constructor of the class),

I'd say that this is more relevant to point (1), i.e. what I referred to as
"call by a qualified name".
No, I mean an unqualified call, like

struct Oops
{
Oops() { g(); } // <-- Call of pure virtual function
virtual void g() = 0;
};

void Oops::g() {}

For any quality compiler you're guaranteed that the code fails to
compile or else that the call g() is implemented as a virtual call (then
resulting in a call of a function that issues a run-time diagnostic), in
spite of the dynamic type of the object being known.

This does not contradict what you wrote, it just sensibly narrows the
(lacking) definition of "actual object" in point 2, namely, that it does
not include this case, or any case where g() is called unqualified from
a non-static member function of Oops.

>and it does not
apply to a call on a named variable of the class, since no such variable
can exist if the class has a pure virtual function;

That would be point (2), yes.
>hence it doesn't
seem to apply to anything in this context, and for the case of a call of
function that's not pure virtual, it's an implementation detail that
only affects the efficiency of a call, if anything, so at the C++ level
it doesn't make much sense to say if that call is virtual or not.

I don't understand what exactly you are referring to by the "implementation
detail" part, since I don't see anything in my post that would be an
implementation detail.
It means that the compiler may choose to implement the call below,

struct Foo { virtual void bar() {} };

int main() { Foo().bar(); }

as a virtual call or as a statically bound call, at its discretion, and
the only way you'll ever know would be by inspecting the machine code.

So I contend that point 2 is not actually meaningful as description of
what happens in practice, because it doesn't apply in any concrete case
I can think of, and AFAIK it does not describe a requirement by the
standard -- I'd leave it out entirely, because a reader will try to
ascribe some meaning that matters, which would likely be incorrect.

Anyway, my description was not intended to be limited to the particular case of
_pure_ virtual functions. It was supposed to be more generic, with only the last
paragraph of my original message dealing with pure virtual functions in particular.
--
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?
Jul 5 '06 #20

P: n/a
* Alf P. Steinbach:
>
struct Oops
{
Oops() { g(); } // <-- Call of pure virtual function
virtual void g() = 0;
};

void Oops::g() {}

For any quality compiler you're guaranteed that the code fails to
compile or else that the call g() is implemented as a virtual call (then
resulting in a call of a function that issues a run-time diagnostic), in
spite of the dynamic type of the object being known.
Except MSVC 7.1... :-(

g++ refuses to compile the code, Comeau warns, MSVC 7.1 happily compiles
it with no diagnostic (!) and calls the Oops::g() implementation.

Did I just say that MSVC 7.1 is not a quality compiler? Seems so.
Since I've maintained the opposite on numerous occasions I have hereby
contradicted myself -- what would life be without contradictions?

--
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?
Jul 5 '06 #21

P: n/a
Alf P. Steinbach wrote:
>...
I don't understand what exactly you are referring to by the "implementation
detail" part, since I don't see anything in my post that would be an
implementation detail.

It means that the compiler may choose to implement the call below,

struct Foo { virtual void bar() {} };

int main() { Foo().bar(); }

as a virtual call or as a statically bound call, at its discretion, and
the only way you'll ever know would be by inspecting the machine code.
Well, the only distinction between the two methods of invoking a function I was
trying to describe in my message is the distinction explicitly mentioned in the
language specification: what I referred to as "dynamic call" is a call that is
resolved in accordance with the _dynamic_ type of the object expression (which
is the standard terminology), while "static calls" are resolved in accordance
with static type of the object expression. This distinction does exist at
conceptual level, i.e. it is specified in the language standard and it does
apply to point (2), as it applies to all other points.

Since you mention the machine code (and taking into account the example above),
you apparently are talking about significantly more lower-level details relevant
to more-or-less "traditional" implementations of the virtual call mechanism. I,
on the other hand, was not trying to get such low-level details involved.

--
Best regards,
Andrey Tarasevich
Jul 5 '06 #22

This discussion thread is closed

Replies have been disabled for this discussion.