Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Pure virtual functions and multiple inheritance

3 views
Skip to first unread message

Kevin Smith

unread,
Jan 30, 2009, 2:45:00 PM1/30/09
to
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?

Jeff Schwab

unread,
Jan 30, 2009, 2:59:30 PM1/30/09
to

Yes. 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() { } };
struct C: virtual A, B { };

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 { };

jameskuyper

unread,
Jan 30, 2009, 3:19:13 PM1/30/09
to

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.

Pete Becker

unread,
Jan 30, 2009, 3:30:03 PM1/30/09
to

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.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

jameskuyper

unread,
Jan 30, 2009, 3:51:42 PM1/30/09
to
Pete Becker wrote:
> On 2009-01-30 15:19:13 -0500, jameskuyper <james...@verizon.net> said:
...

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

Default User

unread,
Jan 30, 2009, 3:57:34 PM1/30/09
to
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

Antoninus Twink

unread,
Jan 30, 2009, 4:45:01 PM1/30/09
to
On 30 Jan 2009 at 20:51, jameskuyper wrote:
> 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?

James Kanze

unread,
Jan 30, 2009, 6:48:05 PM1/30/09
to

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.

--
James Kanze

CBFalconer

unread,
Jan 30, 2009, 9:06:11 PM1/30/09
to

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

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

Pete Becker

unread,
Jan 30, 2009, 9:15:45 PM1/30/09
to
On 2009-01-30 21:06:11 -0500, CBFalconer <cbfal...@yahoo.com> 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?
>
> This is a question about C++, not C. It is off-topic on c.l.c.
> F'ups set.

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

Richard

unread,
Jan 31, 2009, 5:38:44 PM1/31/09
to
Pete Becker <pe...@versatilecoding.com> writes:

> On 2009-01-30 21:06:11 -0500, CBFalconer <cbfal...@yahoo.com> 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?
>>
>> This is a question about C++, not C. It is off-topic on c.l.c.
>> F'ups set.
>
> 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.

Kaz Kylheku

unread,
Feb 1, 2009, 2:43:22 AM2/1/09
to

["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.

Kaz Kylheku

unread,
Feb 1, 2009, 3:09:11 AM2/1/09
to
["Followup-To:" header set to comp.lang.c.]

On 2009-01-30, Jeff Schwab <je...@schwabcenter.com> wrote:
> 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.

Keith Thompson

unread,
Feb 1, 2009, 4:11:00 AM2/1/09
to
Kaz Kylheku <kkyl...@gmail.com> writes:
> ["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.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Pete Becker

unread,
Feb 1, 2009, 6:45:35 AM2/1/09
to
On 2009-02-01 04:11:00 -0500, Keith Thompson <ks...@mib.org> said:

> Kaz Kylheku <kkyl...@gmail.com> writes:
>> ["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;

The original poster presumably will look at comp.lang.c for an answer,
and seeing a redirection will send him to the right place.

> I can't imagine why you'd direct followups to comp.lang.c.

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

Default User

unread,
Feb 1, 2009, 2:34:37 PM2/1/09
to
Pete Becker wrote:

> On 2009-02-01 04:11:00 -0500, Keith Thompson <ks...@mib.org> said:

> > I can't imagine why you'd direct followups to comp.lang.c.
>
> 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 <kkyl...@gmail.com>
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

CBFalconer

unread,
Feb 1, 2009, 9:12:16 PM2/1/09
to
F'ups set to comp.lang.c++, because this discusses C++, not C.
There is no other added information to this post.

Kaz Kylheku wrote:
>
> ["Followup-To:" header set to comp.lang.c.]

--

Kaz Kylheku

unread,
Feb 1, 2009, 9:21:06 PM2/1/09
to
On 2009-02-02, CBFalconer <cbfal...@yahoo.com> wrote:
> 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!

Keith Thompson

unread,
Feb 1, 2009, 9:28:32 PM2/1/09
to

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.

Richard Harter

unread,
Feb 1, 2009, 9:58:01 PM2/1/09
to

Please refrain from using profanity to express your entirely
understandable anger. In the mean time, isn't there anyone among
your family, friends, and relatives who isn't quite right? Don't
you make extra allowances for them? Think of Charles that way
and give him lots of slack.

Richard Harter, c...@tiac.net
http://home.tiac.net/~cri, http://www.varinoma.com
I'm not crazy; I'm a role model for people who are crazy.

CBFalconer

unread,
Feb 1, 2009, 11:12:18 PM2/1/09
to

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.

CBFalconer

unread,
Feb 2, 2009, 6:14:40 PM2/2/09
to

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

jaysome

unread,
Feb 3, 2009, 2:48:27 AM2/3/09
to
On Sun, 01 Feb 2009 21:12:16 -0500, CBFalconer <cbfal...@yahoo.com>
wrote:

>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

Zach

unread,
Feb 3, 2009, 8:21:09 PM2/3/09
to


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

Zach

0 new messages