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

"C++ with Interfaces" (article in CUJ vol 22 no 9)

P: n/a
Interesting article. However, it starts with an example which I find
rather misleading. I hope the author (Christopher Diggins) wouldn't
mind if I post a quote from the article. I know he probably reads or
even writes to c.l.c++.m sometimes.

Christopher gives this [pseudo-]code (yes, it's not C++):

interface IFuBar {
contract:
void FuBar();
};

struct BaseFuBar {
void FuBar() { std::cout << "BaseFuBar"; }
};

struct DerivedFuBar : public BaseFuBar {
void FuBar() { std::cout << "DerivedFuBar"; }
};

main() {
DerivedFuBar d;
BaseFuBar& b = d;
IFuBar i = b;
i.FuBar(); // outputs BaseFuBar
}

and then claims that "the common way to approximate this design
in standard C++ is:"

struct AbcFuBar {
virtual void FuBar() = 0;
};

// vb: missing #include <iostream>

struct BaseFuBar : public AbcFuBar { // vb: public is unnecessary
void FuBar() { std::cout << "BaseFuBar"; }
};

struct DerivedFuBar : public BaseFuBar {
void FuBar() { std::cout << "DerivedFuBar"; }
};

main() { // vb: where is 'int'?
DerivedFuBar d;
BaseFuBar& b = d; /// ************************
AbcFuBar& a = b;
a.FuBar(); // output DerivedFuBar
}

Well, simple superfluosity of 'public', the missing <iostream>, and the
absense of 'main' return value type aside, the code seems logical, yes?

I submit that by changing a single character on the line marked with
asterisks, the desired behaviour can be _correctly_ implemented:

BaseFuBar b = d;

contrary to what the author implies.

Now, I am thinking: should I really read the rest of the article after
seeing that and

main() {
...

in a supposedly _standard_ C++ program?

Christopher is a developer of Heron, another language. I am wondering,
do we really need another language developed because somebody hasn't got
around to learning existing ones well enough? Nah, that can't be it...

Anyway...

Victor
Jul 22 '05 #1
Share this Question
Share on Google+
17 Replies


P: n/a
* Victor Bazarov:

struct AbcFuBar {
virtual void FuBar() = 0;
};

// vb: missing #include <iostream>

struct BaseFuBar : public AbcFuBar { // vb: public is unnecessary
void FuBar() { std::cout << "BaseFuBar"; }
};

struct DerivedFuBar : public BaseFuBar {
void FuBar() { std::cout << "DerivedFuBar"; }
};

main() { // vb: where is 'int'?
DerivedFuBar d;
BaseFuBar& b = d; /// ************************
AbcFuBar& a = b;
a.FuBar(); // output DerivedFuBar
}

Well, simple superfluosity of 'public', the missing <iostream>, and the
absense of 'main' return value type aside, the code seems logical, yes?

I submit that by changing a single character on the line marked with
asterisks, the desired behaviour can be _correctly_ implemented:

BaseFuBar b = d;

contrary to what the author implies.


Haven't read the article (do you have a link?), but:

What is the desired behavior?

Judging from what you write it is to get a call of BaseFuBar::FuBar?

That's easy to achieve as you've shown; there are also other ways.

Btw. you're posting in clc++, not clc++m... ;-)

--
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 22 '05 #2

P: n/a

"Alf P. Steinbach" wrote:
[...]
What is the desired behavior?


Virtual dispatch with Warp 9.9999 velocity and zero space overhead.

Lieutenant Commander Data is full of such things.

regards,
alexander.
Jul 22 '05 #3

P: n/a
Alf P. Steinbach wrote:
* Victor Bazarov:
struct AbcFuBar {
virtual void FuBar() = 0;
};

// vb: missing #include <iostream>

struct BaseFuBar : public AbcFuBar { // vb: public is unnecessary
void FuBar() { std::cout << "BaseFuBar"; }
};

struct DerivedFuBar : public BaseFuBar {
void FuBar() { std::cout << "DerivedFuBar"; }
};

main() { // vb: where is 'int'?
DerivedFuBar d;
BaseFuBar& b = d; /// ************************
AbcFuBar& a = b;
a.FuBar(); // output DerivedFuBar
}

Well, simple superfluosity of 'public', the missing <iostream>, and the
absense of 'main' return value type aside, the code seems logical, yes?

I submit that by changing a single character on the line marked with
asterisks, the desired behaviour can be _correctly_ implemented:

BaseFuBar b = d;

contrary to what the author implies.

Haven't read the article (do you have a link?), but:


No, I don't have a link. I just have my copy of the magazine.
What is the desired behavior?
As I understood from the pseudo-code it's to make the BaseFuBar subobject
to do its thing, but not the DerivedFuBar.
Judging from what you write it is to get a call of BaseFuBar::FuBar?
I thought so.
That's easy to achieve as you've shown; there are also other ways.
You should post your versions.
Btw. you're posting in clc++, not clc++m... ;-)


I know. I rarely post in c.l.c++.m. Too 'm' for my taste.

V
Jul 22 '05 #4

P: n/a
* Victor Bazarov:

main() { // vb: where is 'int'?
DerivedFuBar d;
BaseFuBar& b = d; /// ************************
AbcFuBar& a = b;
a.FuBar(); // output DerivedFuBar
}

What is the desired behavior?


As I understood from the pseudo-code it's to make the BaseFuBar subobject
to do its thing, but not the DerivedFuBar.
Judging from what you write it is to get a call of BaseFuBar::FuBar?


I thought so.
That's easy to achieve as you've shown; there are also other ways.


You should post your versions.


Well one unsafe way to avoid copying is

a.BaseFubar::FuBar();

and one more safe way to capture the the essence of having two diffent
behaviors of same virtual function on same object is to provide an
interface- getter in BaseFuBar

AbcFuBar a& = b.theBaseAndBaseOnlyFuBarInterface();

which can be implemented e.g. on a contained object in BaseFuBar,

but I question the wisdom of the whole thing, because when the object
is really a DerivedFuBar then doing the BaseFuBar thing might break
the class invariant of DerivedFuBar (I think that's also the main reason
why public virtual functions are frowned on by purists).

Btw. you're posting in clc++, not clc++m... ;-)


I know. I rarely post in c.l.c++.m. Too 'm' for my taste.


I meant, are you sure the author of that article is reading _this_ group?

--
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 22 '05 #5

P: n/a
Alf P. Steinbach wrote:
* Victor Bazarov:
main() { // vb: where is 'int'?
DerivedFuBar d;
BaseFuBar& b = d; /// ************************
AbcFuBar& a = b;
a.FuBar(); // output DerivedFuBar
}
What is the desired behavior?
As I understood from the pseudo-code it's to make the BaseFuBar subobject
to do its thing, but not the DerivedFuBar.

Judging from what you write it is to get a call of BaseFuBar::FuBar?


I thought so.

That's easy to achieve as you've shown; there are also other ways.


You should post your versions.

Well one unsafe way to avoid copying is

a.BaseFubar::FuBar();


Why is it unsafe?
and one more safe way to capture the the essence of having two diffent
behaviors of same virtual function on same object is to provide an
interface- getter in BaseFuBar

AbcFuBar a& = b.theBaseAndBaseOnlyFuBarInterface();

which can be implemented e.g. on a contained object in BaseFuBar,

but I question the wisdom of the whole thing, because when the object
is really a DerivedFuBar then doing the BaseFuBar thing might break
the class invariant of DerivedFuBar (I think that's also the main reason
why public virtual functions are frowned on by purists).


To be honest, I struggled to understand whey the author wanted the
"base" (intermediate) version of the function called in the first
place. That was completely unclear from the article. Perhaps it's
just the thing: I didn't get the fact that the whole "interface"
discussion is academical.

What's your take on it?
Btw. you're posting in clc++, not clc++m... ;-)


I know. I rarely post in c.l.c++.m. Too 'm' for my taste.

I meant, are you sure the author of that article is reading _this_ group?


No. Nor do I really care. I posted to express my opinion (possibly in
a too convoluted way), not to bring something to his attention. CUJ
publishes e-mail addresses of authors in case somebody wants to contact
them. I didn't. I am, on the other hand, interested in the opinions of
the community at large, especially considering that rarely topics from
c.l.c++.m trickle down to c.l.c++ so folks here participate.

Victor
Jul 22 '05 #6

P: n/a
* Victor Bazarov:
* Alf:

Well one unsafe way to avoid copying is

a.BaseFubar::FuBar();
Why is it unsafe?


First, should be 'b' not 'a' there.

It's unsafe because
when the object
is really a DerivedFuBar then doing the BaseFuBar thing might break
the class invariant of DerivedFuBar

e.g. DerivedFooBar might add an update of some cached information
which is assumed to always be in synch with the rest and valid.

I didn't get the fact that the whole "interface"
discussion is academical.

What's your take on it?


Don't know because I don't know what the discussion is... :-)

--
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 22 '05 #7

P: n/a
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:bE***************@newsread1.dllstx09.us.to.ve rio.net...
[snip]


Interfaces can be useful. Here's an example:

Suppose I have a system in which there are bunches of objects graphically
drawn on the screen (yes, I know that can't be done in STL, it's just an
example). Suppose I want to implement a drag and drop UI. I want some
objects to be able to be able to have other objects dropped on them, but I
want other objects not to have that functionality. Hence, I create an
interface:

class DropTargetable
{
public:
virtual bool canAcceptDrop(DrawnObj info) = 0;
virtual void acceptDrop(DrawnObj info) = 0;
}

Methods that dealt with a dropping would simply call canAcceptDrop on
whatever they were trying to drop something on, and if it could, they would
call accept drop, where info would be whatever the user had clicked on.

That example is probably more practical than looking at a FooBar example.

Yours,

James

PS, if I missed the point, sorry. =) This is just what I understood to be
your question about interfaces.
Jul 22 '05 #8

P: n/a

Victor Bazarov wrote:
[...]
I meant, are you sure the author of that article is reading _this_ group?


No. Nor do I really care. I posted to express my opinion (possibly in
a too convoluted way), not to bring something to his attention. CUJ
publishes e-mail addresses of authors in case somebody wants to contact
them. I didn't. I am, on the other hand, interested in the opinions of
the community at large, especially considering that rarely topics from
c.l.c++.m trickle down to c.l.c++ so folks here participate.


Bazarov, Bazarov. Community at large really loved the idea. Tons
of kudos.

http://google.com/groups?threadm=qVi....videotron.net
(Subject: C++ with interfaces)

regards,
alexander.
Jul 22 '05 #9

P: n/a
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:bE***************@newsread1.dllstx09.us.to.ve rio.net...
Interesting article. However, it starts with an example which I find
rather misleading. I hope the author (Christopher Diggins) wouldn't
mind if I post a quote from the article. I know he probably reads or
even writes to c.l.c++.m sometimes.

Christopher gives this [pseudo-]code (yes, it's not C++):

interface IFuBar {
contract:
void FuBar();
};

struct BaseFuBar {
void FuBar() { std::cout << "BaseFuBar"; }
};

struct DerivedFuBar : public BaseFuBar {
void FuBar() { std::cout << "DerivedFuBar"; }
};

main() {
DerivedFuBar d;
BaseFuBar& b = d;
IFuBar i = b;
i.FuBar(); // outputs BaseFuBar
}

and then claims that "the common way to approximate this design
in standard C++ is:"

struct AbcFuBar {
virtual void FuBar() = 0;
};

// vb: missing #include <iostream>

struct BaseFuBar : public AbcFuBar { // vb: public is unnecessary
void FuBar() { std::cout << "BaseFuBar"; }
};

struct DerivedFuBar : public BaseFuBar {
void FuBar() { std::cout << "DerivedFuBar"; }
};

main() { // vb: where is 'int'?
DerivedFuBar d;
BaseFuBar& b = d; /// ************************
AbcFuBar& a = b;
a.FuBar(); // output DerivedFuBar
}

Well, simple superfluosity of 'public', the missing <iostream>, and the
absense of 'main' return value type aside, the code seems logical, yes?

I submit that by changing a single character on the line marked with
asterisks, the desired behaviour can be _correctly_ implemented:

BaseFuBar b = d;

contrary to what the author implies.


After reading up a little bit on these interfaces, I think I understand what
the author was trying to point out. While it is true that you _can_ get
the same output as the code that uses interfaces, you have to create another
instance of AbcFuBar to do it. IFuBar, on the other hand, does not perform
any slicing and is operating on the DerivedFooBar instance created in the
main function.

Also, if I understand correctly, the following code will display
"DerivedFuBar" without slicing as well:

IFuBar i2 = d;
i2.FuBar(); // outputs DerivedFuBar

Under the covers, the interface is maintaining a pointer to the object and
invoking the FuBar method. This means that the interface is usable by any
class that implements the required methods, not just those that choose to
inherit from it, and it can invoke methods on objects without using the
standard dynamic dispatching mechanisms used by the second example. It also
means that the same interface could invoke base class functions or derived
class functions on the same object, if they both have the same name and are
not virtual, which is something that you can't do with virtual methods in
ABCs.

I don't know if this functionality is necessary, but it sounds neat.

--
David Hilsee
Jul 22 '05 #10

P: n/a
"David Hilsee" <da*************@yahoo.com> wrote...
[...]

I don't know if this functionality is necessary, but it sounds neat.


That was exactly my point. I couldn't quite grasp (beyond the regular
gripe about performance and size "problems" associated with virtual
functions) what the author's idea behind it was. Besides, looking at
the first example, why would anyone want to circumvent calling the
final overrider (without using any special notation).

I'll keep reading about it, I guess.

V
Jul 22 '05 #11

P: n/a
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:LveQc.227865$JR4.119146@attbi_s54...
"David Hilsee" <da*************@yahoo.com> wrote...
[...]

I don't know if this functionality is necessary, but it sounds neat.


That was exactly my point. I couldn't quite grasp (beyond the regular
gripe about performance and size "problems" associated with virtual
functions) what the author's idea behind it was. Besides, looking at
the first example, why would anyone want to circumvent calling the
final overrider (without using any special notation).


My understanding was that the DerivedFuBar class never intended to override
the FuBar function. I think that's why the BaseFuBar class did not declare
it virtual. Instead, it provided a member function that could optionally be
called by the IFuBar interface instead of BaseFuBar's member function, which
is something one cannot do if the "interface" is instead implemented as
virtual functions in a base class. It's more flexible than the virtual
function approach, but I've never desired that sort of functionality before,
so I don't understand why it is useful in a practical sense.

--
David Hilsee
Jul 22 '05 #12

P: n/a
Victor Bazarov wrote:
Interesting article. However, it starts with an example which I find
rather misleading. I hope the author (Christopher Diggins) wouldn't
mind if I post a quote from the article. I know he probably reads or
even writes to c.l.c++.m sometimes.

Christopher gives this [pseudo-]code (yes, it's not C++):

interface IFuBar {
contract:
void FuBar();
};

struct BaseFuBar {
void FuBar() { std::cout << "BaseFuBar"; }
};

struct DerivedFuBar : public BaseFuBar {
void FuBar() { std::cout << "DerivedFuBar"; }
};

main() {
DerivedFuBar d;
BaseFuBar& b = d;
IFuBar i = b;
i.FuBar(); // outputs BaseFuBar
}

and then claims that "the common way to approximate this design
in standard C++ is:"

struct AbcFuBar {
virtual void FuBar() = 0;
};

// vb: missing #include <iostream>

struct BaseFuBar : public AbcFuBar { // vb: public is unnecessary
void FuBar() { std::cout << "BaseFuBar"; }
};

struct DerivedFuBar : public BaseFuBar {
void FuBar() { std::cout << "DerivedFuBar"; }
};

main() { // vb: where is 'int'?
DerivedFuBar d;
BaseFuBar& b = d; /// ************************
AbcFuBar& a = b;
a.FuBar(); // output DerivedFuBar
}

Well, simple superfluosity of 'public',

Which is not an error and also is more obvious to the eye (reduces the
time cost of some thoughts).

the missing <iostream>, and the
absense of 'main' return value type aside, the code seems logical, yes?

I submit that by changing a single character on the line marked with
asterisks, the desired behaviour can be _correctly_ implemented:

BaseFuBar b = d;

contrary to what the author implies.

No you are wrong. What the author does in essence is:
int main()
{
DerivedFuBar d;

AbcFuBar &a = d;

a.FuBar();
}

or he could also use a base class pointer:

AbcFuBar *pa=&d;

pa->Fubar();

In any case in C++ world this kind of base class is called an "abstract
base class" or "abstract interface" anyway.




Now, I am thinking: should I really read the rest of the article after
seeing that and

main() {
...

in a supposedly _standard_ C++ program?

Well he apparently has stuck in the pre standard time. It could be
worse, it could have been void main() :-)


Regards,

Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #13

P: n/a
"Ioannis Vranos" <iv*@guesswh.at.grad.com> wrote in message
news:ce***********@ulysses.noc.ntua.gr...
[snip]
the missing <iostream>, and the
absense of 'main' return value type aside, the code seems logical, yes?

I submit that by changing a single character on the line marked with
asterisks, the desired behaviour can be _correctly_ implemented:

BaseFuBar b = d;

contrary to what the author implies.

No you are wrong. What the author does in essence is:
int main()
{
DerivedFuBar d;

AbcFuBar &a = d;

a.FuBar();
}

or he could also use a base class pointer:

AbcFuBar *pa=&d;

pa->Fubar();

In any case in C++ world this kind of base class is called an "abstract
base class" or "abstract interface" anyway.


Victor was pointing out that one could get the same output as the first
example by slicing the derived object. He modified that line of code to
show how it could be done. He wasn't demonstrating what the author's code
really did, which is essentially what you just provided.

--
David Hilsee
Jul 22 '05 #14

P: n/a
Victor Bazarov wrote:
I submit that by changing a single character on the line marked with
asterisks, the desired behaviour can be _correctly_ implemented:

BaseFuBar b = d;


Creating a _copy_ of the BaseFuBar subobject isn't something that could
easily be called a "common way to appoximate" the intended design.
could it? I mean copying can have quite some expensive effects..

Another way of "approximation" would be to write a
thunking-implementation of IFuBar:

template<class T>
struct IFuBarImpl : public IFuBar
{
T &impl;
void FuBar() { impl->FuBar(); }
};

This has the same effect without slicing, but is more extensive and less
confortable to use, may involve argument/return value copies (if you
use IFuBar). So I think the author has a point here: If you want to
extract a type, you're adding overhead somewhere.

In fact, to become historical, GNU C++ almost *had* exactly what the
author suggested in form of the "signature" extension which hasn't
survived the transition to version 3.* -- you could take this as an
evolutionary argument for the significance of the proposed language
construct to the c++ community...

Marco

Jul 22 '05 #15

P: n/a
Marco Manfredini wrote:
In fact, to become historical, GNU C++ almost *had* exactly what the
author suggested in form of the "signature" extension which hasn't
survived the transition to version 3.* -- you could take this as an
evolutionary argument for the significance of the proposed language
construct to the c++ community...


There is no need for interfaces in ISO C++, and if there was C++/CLI one
should be the first candidate (as with other things like properties,
events etc).


Regards,

Ioannis Vranos

http://www23.brinkster.com/noicys
Jul 22 '05 #16

P: n/a
On Wed, 04 Aug 2004 14:10:25 -0400, Victor Bazarov
<v.********@comAcast.net> wrote:
Interesting article.


IIRC, the discussions on comp.std.c++ and comp.lang.c++.moderated
concluded that the feature might be a bit error prone (since you don't
get the final overrider called, as is expected by OO programmers in
general), and a better way to add it would be to improve the template
metaprogramming and library writing facilities of the language so that
a library based solution could be written (since the feature probably
isn't important enough to take up language design time on its own).

Tom
Jul 22 '05 #17

P: n/a
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:bE***************@newsread1.dllstx09.us.to.ve rio.net...
Interesting article. However, it starts with an example which I find
rather misleading. I hope the author (Christopher Diggins) wouldn't
mind if I post a quote from the article. I know he probably reads or
even writes to c.l.c++.m sometimes.
I am pleased that you found it worth-while to post.
Christopher gives this [pseudo-]code (yes, it's not C++):

interface IFuBar {
contract:
void FuBar();
};

struct BaseFuBar {
void FuBar() { std::cout << "BaseFuBar"; }
};

struct DerivedFuBar : public BaseFuBar {
void FuBar() { std::cout << "DerivedFuBar"; }
};

main() {
DerivedFuBar d;
BaseFuBar& b = d;
IFuBar i = b;
i.FuBar(); // outputs BaseFuBar
}

and then claims that "the common way to approximate this design
in standard C++ is:"

struct AbcFuBar {
virtual void FuBar() = 0;
};

// vb: missing #include <iostream>

struct BaseFuBar : public AbcFuBar { // vb: public is unnecessary
void FuBar() { std::cout << "BaseFuBar"; }
};

struct DerivedFuBar : public BaseFuBar {
void FuBar() { std::cout << "DerivedFuBar"; }
};

main() { // vb: where is 'int'?
DerivedFuBar d;
BaseFuBar& b = d; /// ************************
AbcFuBar& a = b;
a.FuBar(); // output DerivedFuBar
}

Well, simple superfluosity of 'public', the missing <iostream>, and the
absense of 'main' return value type aside, the code seems logical, yes?

I submit that by changing a single character on the line marked with
asterisks, the desired behaviour can be _correctly_ implemented:

BaseFuBar b = d;

contrary to what the author implies.
That line in the strict context of the example (with the fixes you mentioned
applied) would produce the same output, but would not behave the same with
regards to to object allocation/deallocation/assignment/initialization. My
intention though was to show an example for the design technique. I would
have preferred to not use a (pesudo-)code example using FuBar, but some
readers prefer examples.

Nonetheless, I still firmly believe that the code I placed is more accurate
of the general technique of implementing "interfaces" in C++.
Now, I am thinking: should I really read the rest of the article after
seeing that and

main() {
...

in a supposedly _standard_ C++ program?
Not if you don't want to.
Christopher is a developer of Heron, another language. I am wondering,
do we really need another language developed because somebody hasn't got
around to learning existing ones well enough? Nah, that can't be it...


I always forget that the best measure of my work is whether or not I put
"int" in front of "main" when writing a C++ program. Maybe I should place
more importance on the vagaries of the ever changing C++ syntax, rather than
developing new techniques and ideas.

--
Christopher Diggins
http://www.heron-language.com
Jul 22 '05 #18

This discussion thread is closed

Replies have been disabled for this discussion.