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

V

Victor Bazarov

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
 
A

Alf P. Steinbach

* 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

Alexander Terekhov

:
[...]
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.
 
V

Victor Bazarov

Alf said:
* Victor Bazarov:



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
 
A

Alf P. Steinbach

* Victor Bazarov:
As I understood from the pseudo-code it's to make the BaseFuBar subobject
to do its thing, but not the DerivedFuBar.


I thought so.


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

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?
 
V

Victor Bazarov

Alf said:
* Victor Bazarov:



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

Alf P. Steinbach

* Victor Bazarov:
* Alf:

Why is it unsafe?

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

It's unsafe becausee.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

Aguilar, James

Victor Bazarov said:

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

Alexander Terekhov

Victor Bazarov wrote:
[...]
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/[email protected]
(Subject: C++ with interfaces)

regards,
alexander.
 
D

David Hilsee

Victor Bazarov said:
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.
 
V

Victor Bazarov

David Hilsee said:
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
 
D

David Hilsee

Victor Bazarov said:
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.
 
I

Ioannis Vranos

Victor said:
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
 
D

David Hilsee

[snip]
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.
 
M

Marco Manfredini

Victor said:
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
 
I

Ioannis Vranos

Marco said:
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
 
T

tom_usenet

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
 
C

christopher diggins

Victor Bazarov said:
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.
 
C

christopher diggins

tom_usenet said:
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),

On the other hand, is this not the behaviour expected by more naive
programmers?
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

There was a suggestion, by David Abrahams, that *maybe* better
metaprogramming support would allow a library based sol'n for interfaces in
the manner suggested at http://www.heron-language.com/cpp-iop.html . This
was done in a somewhat vague and dismissive manner, and no one demonstrated
what form this would take and how it could be done.

(since the feature probably
isn't important enough to take up language design time on its own).

This depends on what the goals of the language designers of C++ are. It
doesn't seem to be a high priority to improve the efficiency of the run-time
polymorphic facilities in C++. The argument has been for quite some time
that things are good enough the way they are and that programmers simply
just shouldn't use heavily polymorphic designs (correct me if I am wrong in
this regard). This is troublesome because it is one of the rare cases in C++
where a perfectly valid design approach is dismissed because it doesn't fit
well with the language design.
 
C

christopher diggins

Ioannis Vranos said:
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).

So are you saying there is a need or there isn't? Why should the CLI
canidate be considered first? It is much less efficient.
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top