pure virttual function

S

sks

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

sks

Murali said:
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?
 
A

Alf P. Steinbach

* Murali Krishna:
*sks:

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.
 
T

TB

Murali Krishna skrev:
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;
}
 
A

Alf P. Steinbach

* Stuart Golodetz:
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.
 
S

Stuart Golodetz

Alf P. Steinbach said:
* Stuart Golodetz:

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
 
M

Murali Krishna

sks said:
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
 
R

Rolf Magnus

Alf said:
* Murali Krishna:
*sks:

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.
 
A

Alf P. Steinbach

* Rolf Magnus:
Alf said:
* 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.
 
E

Earl Purple

Alf said:
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).
 
R

Rolf Magnus

Earl said:
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.
 
?

=?iso-8859-1?q?Kirit_S=E6lensminde?=

sks said:
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
 
A

Andrey Tarasevich

sks said:
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.
 
A

Alf P. Steinbach

* 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

Andrey Tarasevich

Alf said:
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-lite/virtual-functions.html#faq-20.2
http://www.parashift.com/c++-faq-lite/virtual-functions.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.
 
A

Alf P. Steinbach

* Andrey Tarasevich:
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-lite/virtual-functions.html#faq-20.2
http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.3


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.

That would be point (2), yes.


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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,431
Messages
2,571,678
Members
48,796
Latest member
Greg L.

Latest Threads

Top