Pure virtual functions and multiple inheritance

K

Kevin Smith

Can I provide the implementation of a pure virtual function by inheriting
from another class? eg.:

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

};

class B{
public:
void f(){};

};

class C: public A, public B{};

My compiler (VC++) tells me that C is an abstract class, even though there
is a public implementation of f() in C. Is this Standard?
 
J

jameskuyper

Kevin said:
Can I provide the implementation of a pure virtual function by inheriting
from another class? eg.:

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

};

class B{
public:
void f(){};

};

class C: public A, public B{};

My compiler (VC++) tells me that C is an abstract class, even though there
is a public implementation of f() in C. Is this Standard?

This message should not have been posted to comp.lang.c. As far as the
C programming language is concerned, that code is just a long series
of syntax errors.
 
J

jameskuyper

Pete said:
On 2009-01-30 15:19:13 -0500, jameskuyper <[email protected]> said: ....

This message should not have been posted to comp.lang.c++. As far as
the C++ programmiong language is concerned, that code is just fine.

That is not sufficient to justify cross-posting his question to both
groups. However, his cross-posting was sufficient justification for me
to cross-post my complaint. Just because he cross-posts to both
newsgroups does not guarantee that he monitors both of them, so
restricting my response to comp.lang.c would have been inadequate. I'd
have used his e-mail address, had it been usable.
 
D

Default User

Pete Becker wrote:

This message should not have been posted to comp.lang.c++. As far as
the C++ programmiong language is concerned, that code is just fine.


I disagree. He is getting a diagnostic, and wants to know if what he
has is standard. It's a legitimate question.




Brian
 
A

Antoninus Twink

However, his cross-posting was sufficient justification for me to
cross-post my complaint.

Your complaint is groundless, so there is no justification for you to
post it anywhere.

Even if it /were/ valid, why not keep it to yourself (or private email)
instead of adding yet more vitriol to the Usenet airwaves and decreasing
clc's SNR still further?
 
J

James Kanze

Can I provide the implementation of a pure virtual function by
inheriting from another class? eg.:
class A{
public:
virtual void f() = 0;
};
class B{
public:
void f(){};
};
class C: public A, public B{};
My compiler (VC++) tells me that C is an abstract class, even
though there is a public implementation of f() in C. Is this
Standard?

Yes. If B intends for B::f() to implement A::f(), then it
should inherit (probably virtually) from A. If it doesn't, then
it's highly unlikely that B::f() will meet the contractual
requirements for A::f(). Not allowing such an implicit override
is an essential safety feature in any language which takes
robustness seriously.

If you know that B::f() does in fact meet the contract of A::f()
(by chance, since the author of B::f() obviously didn't do so
intentionally), you can easily create an intermediate class
which expresses this:

class BImplementsA : private B, public virtual A
{
public:
virtual void f() { B::f() ; }
} ;

If you then inherit from BImplementsA, there will be no problem.
 
C

CBFalconer

Kevin said:
Can I provide the implementation of a pure virtual function by
inheriting from another class? eg.:

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

class B{
public:
void f(){};
};

class C: public A, public B{};

My compiler (VC++) tells me that C is an abstract class, even
though there is a public implementation of f() in C. Is this
Standard?

This is a question about C++, not C. It is off-topic on c.l.c.
F'ups set.
 
R

Richard

Pete Becker said:
This response is about comp.lang.c, not comp.lang.c++. It is off-topic
on comp.lang.c++. Definitely F'upped.

Chuck Falconer is a c.l.c troll who for some reason insists on bullying
people. Most people ignore him.
 
K

Kaz Kylheku

Can I provide the implementation of a pure virtual function by inheriting
from another class? eg.:

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

};

class B{
public:
void f(){};

};

class C: public A, public B{};

My compiler (VC++) tells me that C is an abstract class, even though there
is a public implementation of f() in C. Is this Standard?

["Followup-To:" header set; replies to this article will be configured
to go to comp.lang.c++, unless you manually edit the header.]

It is not standard, and other compilers also won't like this, like GNU
C++ 4.3.2.

The pure virtual simply isn't being overridden by a class that isn't deriving
from B. They are two different functions. Note that if you had this:

class A{
public:
virtual void f() { /* A behavior */ }

};

class B{
public:
virtual void f() { /* B behavior */ }
};

and you combine these into the same derived class C, then you still have two
different functions. One does not override the other. There is an A::f and a
B::f. If you have a B& reference to a C object, then calling f gets you B::f
with the B behavior. If you have an A& reference to the object, then calling f
on that reaches A::f with A behavior. Moreover, if you try to call f on a C
object, it will be ambiguous:

C x;
x.f(); // ambiguous call; did you want A::f or B::f?

But if both functions are virtual, and C does implement a void C::f(), then
that overrides both! Now if you call f through an A& reference, you get C::f,
and same via a B& reference.

So in your case, what you need is this:

class C: public A, public B
{
public:
void f() { B::f(); }
};

Now if objects of type C are used through a B class reference, the call to f
goes to B::f, of course. This is not a virtual call. B::f is not virtual
and cannot be overridden. C::f overrides only A::f. The C::f definition
suppresses the lexical visibility of B::f in the C class scope, but does
not override that function.

But if f is called on a C object through an A reference, it is routed to C::f;
it is only thanks to C::f that the call then reaches B::f.
 
K

Kaz Kylheku

["Followup-To:" header set to comp.lang.c.]

Yes, what? It is standard?
What you want is called a "mixin." Of course, the "easy" way is:

struct A { virtual void f() =0; };
struct B: virtual A { void f() { } };

Virtual base classes are a complicated way to solve this. And also,
you are editing one of the original classes. B::f is now virtual,
and overrides the pure virtual A::f.

The virtual inheritance of A ensures that the C object gets only one A. Since
the object has only one A, and since it contains a B which seals the pure
virtual A::f with B::f, the C object has no pure virtuals.

This is like duct-tape.

(In some 13 years of commercial C++ development, I've yet to find use for a
virtual base class, and I'm not sure you understand what they are for).
struct C: virtual A, B { };

See there is no reason for C now to inherit A directly, since it's
getting it from B. You can change this whole thing to:

struct A { virtual void f() = 0; };
struct B: public A { void f() { } };
struct C: public B { };

Look ma, no virtual inheritance.
If that's not an option for you, try this:
struct A { virtual void f() =0; };
struct B { void f() { } };
struct B_mixin: virtual A, private B { void f() { B::f(); } };
struct C: virtual A, B_mixin { };

Yuck. Five years in the Java slammer for you!

But I know a good language lawyer who may be able to get you three.

But at least this doesn't touch A and B. But note that instead
of this B_mixin implementing the override, C can just do it.

The above is a complicated way of doing this:

struct A { virtual void f() =0; };
struct B { void f() { } };
struct C: public A, public B { void f() { B::f() } };

No mixin, no virtual bases. Keep it simple and stupid.

Also note that C doesn't actually solve any problem in your
above solution. So what we can do is simply drop C,
and rename B_mixin to C:

struct A { virtual void f() =0; };
struct B { void f() { } };
// C was called B_mixin; original C gone
struct C: virtual A, private B { void f() { B::f(); } };

Drop the virtual from virtual A, and you get the same thing
again.
 
K

Keith Thompson

Kaz Kylheku said:
["Followup-To:" header set to comp.lang.
[90 lines deleted]

Why? The question, and your response, were entirely specific to C++;
the only connection to C was that the code declared a class of that
name.

I don't understand why you posted your followup to comp.lang.c at all;
I can't imagine why you'd direct followups to comp.lang.c.
 
D

Default User

Pete said:
On 2009-02-01 04:11:00 -0500, Keith Thompson <[email protected]> said:

He didn't. They go to comp.lang.c++, where they belong.

That's incorrect. Here are the basic headers from Kaz's post:

From: Kaz Kylheku <[email protected]>
Subject: Re: Pure virtual functions and multiple inheritance
Newsgroups: comp.lang.c,comp.lang.c++
Followup-To: comp.lang.c


FUs to clc, not clc++.



Brian
 
C

CBFalconer

F'ups set to comp.lang.c++, because this discusses C++, not C.
There is no other added information to this post.

Kaz said:
["Followup-To:" header set to comp.lang.c.]
Jeff Schwab said:

Yes, what? It is standard?
What you want is called a "mixin." Of course, the "easy" way is:

struct A { virtual void f() =0; };
struct B: virtual A { void f() { } };

Virtual base classes are a complicated way to solve this. And also,
you are editing one of the original classes. B::f is now virtual,
and overrides the pure virtual A::f.

The virtual inheritance of A ensures that the C object gets only one A. Since
the object has only one A, and since it contains a B which seals the pure
virtual A::f with B::f, the C object has no pure virtuals.

This is like duct-tape.

(In some 13 years of commercial C++ development, I've yet to find use for a
virtual base class, and I'm not sure you understand what they are for).
struct C: virtual A, B { };

See there is no reason for C now to inherit A directly, since it's
getting it from B. You can change this whole thing to:

struct A { virtual void f() = 0; };
struct B: public A { void f() { } };
struct C: public B { };

Look ma, no virtual inheritance.
If that's not an option for you, try this:
struct A { virtual void f() =0; };
struct B { void f() { } };
struct B_mixin: virtual A, private B { void f() { B::f(); } };
struct C: virtual A, B_mixin { };

Yuck. Five years in the Java slammer for you!

But I know a good language lawyer who may be able to get you three.

But at least this doesn't touch A and B. But note that instead
of this B_mixin implementing the override, C can just do it.

The above is a complicated way of doing this:

struct A { virtual void f() =0; };
struct B { void f() { } };
struct C: public A, public B { void f() { B::f() } };

No mixin, no virtual bases. Keep it simple and stupid.

Also note that C doesn't actually solve any problem in your
above solution. So what we can do is simply drop C,
and rename B_mixin to C:

struct A { virtual void f() =0; };
struct B { void f() { } };
// C was called B_mixin; original C gone
struct C: virtual A, private B { void f() { B::f(); } };

Drop the virtual from virtual A, and you get the same thing
again.
 
K

Kaz Kylheku

F'ups set to comp.lang.c++, because this discusses C++, not C.
There is no other added information to this post.

Thanks for the immensely valuable service of quoting an entire fucking article,
just to give it a different Followup-to, which has no effect on the original
article. Drooling moron!
 
K

Keith Thompson

Kaz Kylheku said:
Thanks for the immensely valuable service of quoting an entire
fucking article, just to give it a different Followup-to, which has
no effect on the original article. Drooling moron!

He was quoting an article *you* posted regarding C++, with exactly
zero C content, on which you set followups to comp.lang.c. Quoting
the whole thing might not have been necessary, but flaming others when
you yourself have screwed up is not a good idea.

Since this article has no C or C++ content, I've directed followups to
alt.dev.null; if you want to post a followup elsewhere, you'll have to
deal with the headers yourself.
 
C

CBFalconer

Kaz said:
Thanks for the immensely valuable service of quoting an entire
fucking article, just to give it a different Followup-to, which
has no effect on the original article. Drooling moron!

I think you have misidentified the idiot. When you mis-set the
follow-up, you arranged for all replies to be sent to c.l.c (where
they have no business). Thus I quoted the whole thing so that the
results would be visible on c.l.c++. There is no perfect way of
compensating for your original error.
 
C

CBFalconer

Kevin said:
Can I provide the implementation of a pure virtual function by
inheriting from another class? eg.:

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

class B{
public:
void f(){};
};

class C: public A, public B{};

My compiler (VC++) tells me that C is an abstract class, even
though there is a public implementation of f() in C. Is this
Standard?

This is off-topic on c.l.c. F'ups set.
 
J

jaysome

F'ups set to comp.lang.c++, because this discusses C++, not C.
There is no other added information to this post.

You top-posted.

Is there some kind of amnesty rule in this newsgroup by where it is
okay to top-post in your reply if you think that the OP to whom you
replied to has F'uped? Or was your top-post just a faux pas?

--
jay
Kaz said:
["Followup-To:" header set to comp.lang.c.]
Jeff Schwab said:
Kevin Smith wrote:

Can I provide the implementation of a pure virtual function by inheriting
from another class? eg.:

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

class B{
public:
void f(){};
};

class C: public A, public B{};

My compiler (VC++) tells me that C is an abstract class, even though there
is a public implementation of f() in C. Is this Standard?

Yes.

Yes, what? It is standard?
What you want is called a "mixin." Of course, the "easy" way is:

struct A { virtual void f() =0; };
struct B: virtual A { void f() { } };

Virtual base classes are a complicated way to solve this. And also,
you are editing one of the original classes. B::f is now virtual,
and overrides the pure virtual A::f.

The virtual inheritance of A ensures that the C object gets only one A. Since
the object has only one A, and since it contains a B which seals the pure
virtual A::f with B::f, the C object has no pure virtuals.

This is like duct-tape.

(In some 13 years of commercial C++ development, I've yet to find use for a
virtual base class, and I'm not sure you understand what they are for).
struct C: virtual A, B { };

See there is no reason for C now to inherit A directly, since it's
getting it from B. You can change this whole thing to:

struct A { virtual void f() = 0; };
struct B: public A { void f() { } };
struct C: public B { };

Look ma, no virtual inheritance.
If that's not an option for you, try this:
struct A { virtual void f() =0; };
struct B { void f() { } };
struct B_mixin: virtual A, private B { void f() { B::f(); } };
struct C: virtual A, B_mixin { };

Yuck. Five years in the Java slammer for you!

But I know a good language lawyer who may be able to get you three.

But at least this doesn't touch A and B. But note that instead
of this B_mixin implementing the override, C can just do it.

The above is a complicated way of doing this:

struct A { virtual void f() =0; };
struct B { void f() { } };
struct C: public A, public B { void f() { B::f() } };

No mixin, no virtual bases. Keep it simple and stupid.

Also note that C doesn't actually solve any problem in your
above solution. So what we can do is simply drop C,
and rename B_mixin to C:

struct A { virtual void f() =0; };
struct B { void f() { } };
// C was called B_mixin; original C gone
struct C: virtual A, private B { void f() { B::f(); } };

Drop the virtual from virtual A, and you get the same thing
again.
 
Z

Zach

Can I provide the implementation of a pure virtual function by inheriting
from another class? eg.:

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

};

class B{
public:
void f(){};

};

class C: public A, public B{};

My compiler (VC++) tells me that C is an abstract class, even though there
is a public implementation of f() in C. Is this Standard?


This is comp.lang.c, questions about C++ are OFF-TOPIC. Please stop
posting this stuff here.

Zach
 

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
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top