Interface without Inheritance

N

nicetan

Is it possible to force a c++ class to implement an interface without inheriting from the abstract base class? I just want to perform a compile time check, make sure these methods are implemented, but not have all the virtualmethods, since I've heard that virtual methods have some performance hit and can't be inlined.

I realize that the performance hit is negligible but why have a performancehit at all when I'm not really inheriting anything, just forcing a certainset of methods to be implemented?

Thanks,
Dan
 
V

Victor Bazarov

Is it possible to force a c++ class to implement an interface without
inheriting from the abstract base class?

Hm... AFAIK, no. Inheriting from an ABC is the only way to _enforce_
implementation.

Sometimes it's possible to provide your own ways to implement interface
without inheritance, like using macros that inject declarations into the
class definition, but those are voluntary, from what I've seen. Perhaps
there is some preprocessor trickery that could be played in that
situation, but nothing immediately comes to mind.
I just want to perform a
compile time check, make sure these methods are implemented, but not
have all the virtual methods, since I've heard that virtual methods
have some performance hit and can't be inlined.

Performance should not be approached based on a rumor. If you think
your implementation has performance impact, you need to *measure* it to
confirm.
I realize that the performance hit is negligible but why have a
performance hit at all when I'm not really inheriting anything, just
forcing a certain set of methods to be implemented?

You can use compile-time asserts (see "static asserts") to verify that
your class has specific methods of specific types, and that's probably
the other solution for you, but then again, if class hasn't been written
yet, it has no name, so how would you know to assert anything based on
that type's implementation?

V
 
N

nicetan

Is it possible to force a c++ class to implement an interface without inheriting from the abstract base class? I just want to perform a compile timecheck, make sure these methods are implemented, but not have all the virtual methods, since I've heard that virtual methods have some performance hitand can't be inlined.



I realize that the performance hit is negligible but why have a performance hit at all when I'm not really inheriting anything, just forcing a certain set of methods to be implemented?



Thanks,

Dan

Great thanks. I don't have any problem with the virtual way if thats the only way. Just wanted to check there wasn't some language feature I was missing. I could also just not have the interface and the compiler will pick up the problem when I actually try to call one of the methods, which might be the way I go.
 
Ö

Öö Tiib

Is it possible to force a c++ class to implement an interface without
inheriting from the abstract base class?

Dynamic interface is usually meant to be pure abstract base class.
Static interface is usually meant to be (possibly templatized) member
functions, functions, functors or lambdas with matching signatures (amount
and type of arguments those functions take, sometimes name is also part of signature).

Class can implement things itself or contain/own something (member or
static object) that implements an interface and only forward the work.
This is work of designer to decide how it is laid out inside of class.
I just want to perform a compile time check, make sure these methods are
implemented, but not have all the virtual methods, since I've heard that
virtual methods have some performance hit and can't be inlined.

That performance hit is too small. Use virtual inheritance
as first thing. The other tricks are way more complex to pull.
You learn every wizardry step by step. You should not take fireball
(template) before magic missile (virtual function) of yours is perfect.
I realize that the performance hit is negligible but why have a
performance hit at all when I'm not really inheriting anything,
just forcing a certain set of methods to be implemented?

Certainly. Find a good book about templates and their usage and
study it. Rest assured, nothing of there is as simple to use as
virtual function. When you have particular question then come back. ;)
 
R

Rui Maciel

Is it possible to force a c++ class to implement an interface without
inheriting from the abstract base class? I just want to perform a compile
time check, make sure these methods are implemented, but not have all the
virtual methods, since I've heard that virtual methods have some
performance hit and can't be inlined.

I realize that the performance hit is negligible but why have a
performance hit at all when I'm not really inheriting anything, just
forcing a certain set of methods to be implemented?

If all you want is to run some compiler checks on a class/module, a possible
technique would be implement a template policy pattern, pass the class you
want to test to your template policy/strategy, and check if the code
compiles.


<code>
#include <iostream>


struct Foo
{
void methodA()
{
std::cout << "Foo::methodA()" << std::endl;
}

void methodB()
{
std::cout << "Foo::methodB()" << std::endl;
}
};


struct Bar
{
void methodA()
{
std::cout << "Bar::methodA()" << std::endl;
}
};


struct Baz
{
void methodB()
{
std::cout << "Baz::methodB()" << std::endl;
}
};

template <class T>
struct TesterPolicy
{
static void test()
{
T t;
t.methodA();
t.methodB();
}
};

int main(void)
{
TesterPolicy<Foo>::test();
TesterPolicy<Bar>::test();
TesterPolicy<Baz>::test();

return 0;
}
</code>


It's also possible to employ the template policy pattern to set up the
interface for a generic algorithm and implement it without requiring any
support for polymorphism. The downside of this is that by following this
route it isn't possible to take advantage of what polymorphism has to offer.


Rui Maciel
 
R

Rui Maciel

Öö Tiib said:
Certainly. Find a good book about templates and their usage and
study it. Rest assured, nothing of there is as simple to use as
virtual function.

Templates aren't the bogeyman you are making it out to be. For example, can
you come up with an example based on inheritance/virtual functions which
implements a policy pattern in a way which is simpler to read and more
concise than the following example?


<example>
#include <iostream>
#include <string>


struct ProductA
{
std::string name() { return "A"; };
std::string review() { return "It's ok"; };
std::string ID() { return "asdf"; };

int bar() {return 1;};
};


struct ProductB
{
std::string name() { return "B"; };
std::string review() { return "It's nice"; };
std::string ID() { return "fdsa"; };

void foo() {};
};


// this isn't a generic programming horror show
template<class T>
struct ProductOveviewPolicy
{
void output(T &t)
{
std::cout << "This is what people think of " << t.name() <<
"\n";
std::cout << "\t«" << t.review() << "»\n";
std::cout << "ID: " << t.ID() << std::endl;
}
};


int main(void)
{
ProductA A;
ProductB B;

ProductOveviewPolicy<ProductA> overview_a;
overview_a.output(A);

ProductOveviewPolicy<ProductB> overview_b;
overview_b.output(B);

return 0;
}
</code>


Rui Maciel
 
Ö

Öö Tiib

Templates aren't the bogeyman you are making it out to be.

Bogeyman? No. Just more complex to use I said.
For example, can you come up with an example based on inheritance/virtual
functions which implements a policy pattern in a way which is simpler to
read and more concise than the following example?

Can you elaborate it bit more about what yours "policy pattern" is
(book/link)? I have so far had impression that it is synonym of
"strategy pattern" that I know well.

This was not certainly strategy pattern. You did not change strategy
(or policy) of some object dynamically run-time.

As for what it did achieve ... then it is easier with interface,
(IMHO but YMMV):

#include <iostream>
#include <string>

struct IOverView
{
virtual std::string name() = 0;
virtual std::string review() = 0;
virtual std::string ID() = 0;
};

void output( IOverView& t )
{
std::cout << "This is what people think of " << t.name() << "\n";
std::cout << "\t«" << t.review() << "»\n";
std::cout << "ID: " << t.ID() << std::endl;
}

struct ProductA
: public IOverView
{
virtual std::string name() override { return "A"; };
virtual std::string review() override { return "It's ok"; };
virtual std::string ID() override { return "asdf"; };

int bar() {return 1;};
};

struct ProductB
: public IOverView
{
virtual std::string name() override { return "B"; };
virtual std::string review() override { return "It's nice"; };
virtual std::string ID() override { return "fdsa"; };

void foo() {};
};

int main()
{
ProductA A; // diagnostics here if something from
ProductB B; // IOverView was not properly implemented

output( A );
output( B );
}
 
D

Dombo

Op 21-Feb-13 18:14, Victor Bazarov schreef:
Hm... AFAIK, no. Inheriting from an ABC is the only way to _enforce_
implementation.

Sometimes it's possible to provide your own ways to implement interface
without inheritance, like using macros that inject declarations into the
class definition, but those are voluntary, from what I've seen. Perhaps
there is some preprocessor trickery that could be played in that
situation, but nothing immediately comes to mind.


Performance should not be approached based on a rumor. If you think
your implementation has performance impact, you need to *measure* it to
confirm.

And if there is a performance hit determine whether or not your
application can live with it (most likely it can). It would be ashame if
the code becomes harder to understand and maintain for no tangible
performance benefit.

As far as inlining is concerned: if the compiler may choose to inline
virtual functions if the compiler is able to determine at compile time
exactly which function implementation is going to be executed. In other
words: there may be not performance hit at all. That's why you should
always measure performance, and not just assume based on rumors or even
past experiences (compilers and linkers do get better).
 
R

Rui Maciel

Öö Tiib said:
Bogeyman? No. Just more complex to use I said.

You've claimed that with templates "nothing of there is as simple to use as
virtual functions", which is quite an emphatic assertion on the alleged
difficulty of using templates. Do you believe that the example I've
provided is harder to use than an equivalent one you can come up based on
inheritance?

Can you elaborate it bit more about what yours "policy pattern" is
(book/link)? I have so far had impression that it is synonym of
"strategy pattern" that I know well.

The gang of four book on design patterns refers to the strategy pattern also
as the policy pattern. The wikipedia article as well. But in this context,
as we are discussing the generic programming implementation, it's more
appropriate to call it by its name, the policy pattern, due to the chapter
on policy-based design that Andrei Alexandrescu wrote in his «Modern C++
design: generic programming and design patterns applied" book.

This was not certainly strategy pattern. You did not change strategy
(or policy) of some object dynamically run-time.

The example was supposed to be concise and to avoid implementing any
algorithm. If you believe it's relevant to the discussion, rename
"Product(A|B)" to, for example, "ConcreteStrategy(HTML|LaTeX)", tweak the
member functions to output the appropriate preamble, header and document
bodies, rename "ProductOverviewPolicy" to "DocumentOutputPolicy", and tweak
its output() member function as appropriate.

As for what it did achieve ... then it is easier with interface,
(IMHO but YMMV):
<snip/>

Easier where? You had to clutter the source code with an extra class
declaration, you were forced to sprinkle pure virtual functions around, and
there are override directives everywhere. How did you make that example any
simpler by adding all that unnecessary cruft?

The generic programming solution achieves the exact same objective, and is
far cleaner, easier to read, and straight-forward.

Food for thought.


Rui Maciel
 
Ö

Öö Tiib

You've claimed that with templates "nothing of there is as simple to use as
virtual functions", which is quite an emphatic assertion on the alleged
difficulty of using templates.

Can you somehow be more specific in your complaint. "nothing is as simple"
means that "everything is more complex". That was exactly what I meant.
Ages of practice of helping newcomers to gain skill with one or other
are shown that it is so. Several even fear to use mundane templates
like the ones in standard library and try to write their own ByteBuffer
Do you believe that the example I've
provided is harder to use than an equivalent one you can come up based on
inheritance?

My main() did look really desolate and simple so I think that usage
indeed was easier. Both 'virtual' and 'override' were added to ProductA and
ProductB members just to document indent and may be removed by language
rules. So there remains just declaration of required interface that is great
to have.
The gang of four book on design patterns refers to the strategy pattern also
as the policy pattern. The wikipedia article as well. But in this context,
as we are discussing the generic programming implementation, it's more
appropriate to call it by its name, the policy pattern, due to the chapter
on policy-based design that Andrei Alexandrescu wrote in his «Modern C++
design: generic programming and design patterns applied" book.

Ok, some sort of contradicting terminology. Better implement real policy
pattern with template and lets compare?
The example was supposed to be concise and to avoid implementing any
algorithm. If you believe it's relevant to the discussion, rename
"Product(A|B)" to, for example, "ConcreteStrategy(HTML|LaTeX)", tweak the
member functions to output the appropriate preamble, header and document
bodies, rename "ProductOverviewPolicy" to "DocumentOutputPolicy", and tweak
its output() member function as appropriate.

Names impress me not. I was about effect achieved. Effect that your code
achieved felt too trivial.
<snip/>

Easier where?

Every single bit of it. You just snipped it. :D
You had to clutter the source code with an extra class
declaration, you were forced to sprinkle pure virtual functions around, and
there are override directives everywhere. How did you make that example any
simpler by adding all that unnecessary cruft?

Lets see your complaints.

1) "extra class" is *the* interface specification. In your example
interface was nowhere specified. So why it was easier?

2) "pure virtual" means that if you want to have the interface you must
override it. '=0' is oh so hard to type?

3) "override" means that it implements or overrides base class
implementation. That results with compile time error if interface
is tiniest bit different in derived class. Try edit IOverView:
'virtual std::string name() const {return "";}'
It is making everything very safe and novice-friendly. 8 characters.

4) I also had redundant 'virtual' in overrides, why you did not complain,
another 7 characters? It just feels more readable and safe, both
'override' and 'virtual' may be removed from overrides by language
rules.
The generic programming solution achieves the exact same objective, and is
far cleaner, easier to read, and straight-forward.

Food for thought.

Shrug. I still do not understand your objective. If it was to have:

ProductOveviewPolicy<ProductB> overview_b;
overview_b.output(B);

.... instead of:

output(B);

.... then that feels not simpler to me. If it was to get error messages
about interface differences somewhere inside of alien template instead
of point of declaration then that feels also not simpler for me.

I feel that you just want to argue. There is nothing to argue, I said
what I meant and even your own example feels to support mine points
better than yours. Dynamic polymorphism is often actually needed,
it can be used elegantly for doing lot of things for what it is not
actually needed and it seems to be easier to learn for novices than
template metaprogramming.
 
R

Rui Maciel

Öö Tiib said:
Can you somehow be more specific in your complaint. "nothing is as simple"
means that "everything is more complex". That was exactly what I meant.
Ages of practice of helping newcomers to gain skill with one or other
are shown that it is so.
<snip/>

If people like you keep reiterating this nonsense of mindlessly telling
newbies to stay away from the templates bogeyman because they are supposed
to be "way more complex" than anything else, even when this assertion flies
in the face of reality, then this nonsense turns into a self-fulfilling
prophecy. Before you know it, that newbie will also be mindlessly
reiterating this nonsense because he says so, because others like him say
so, and because "ages of practice" tells him that the templates bogeyman is
far too complex to be understood by mere mortals.

My main() did look really desolate and simple so I think that usage
indeed was easier. Both 'virtual' and 'override' were added to ProductA
and ProductB members just to document indent and may be removed by
language rules. So there remains just declaration of required interface
that is great to have.

You didn't answered the question. Do you actually believe the template
example is harder to use or to understand?

Ok, some sort of contradicting terminology.

You can always get in contact with the team behind the gang of four book and
alexandrescu to tell them they are wrong. But nitpicking about the name of
a design pattern has absolutely nothing to do with this topic.

Names impress me not.

It appears otherwise, because you've wasted time complaining about it.

Every single bit of it. You just snipped it. :D

The code is available in the server. Snipping redundant content doesn't
hide it from the world.

Lets see your complaints.

1) "extra class" is *the* interface specification. In your example
interface was nowhere specified. So why it was easier?

2) "pure virtual" means that if you want to have the interface you must
override it. '=0' is oh so hard to type?

3) "override" means that it implements or overrides base class
implementation. That results with compile time error if interface
is tiniest bit different in derived class. Try edit IOverView:
'virtual std::string name() const {return "";}'
It is making everything very safe and novice-friendly. 8 characters.

4) I also had redundant 'virtual' in overrides, why you did not complain,
another 7 characters? It just feels more readable and safe, both
'override' and 'virtual' may be removed from overrides by language
rules.

You are spending too much time and effort trying to explain your inheritance
example. What does this say about its simplicity? And instead of avoiding
the question, just stop waltzing around the issue and simply answer the
question: is the template example any harder to understand than the
inheritance one?

Shrug. I still do not understand your objective. If it was to have:

ProductOveviewPolicy<ProductB> overview_b;
overview_b.output(B);

... instead of:

output(B);

... then that feels not simpler to me.

So, is the template example harder to understand, or does the inheritance
example only starts to become as simple as the template one once you remove
any reference to the need of declaring extra classes, adding extra virtual
function definitions and sprinkling overriding directives? You know, the
stuff that is required to make it work.

I feel that you just want to argue. There is nothing to argue, I said
what I meant and even your own example feels
<snip/>

I've asked you a simple question: if you could come up with a policy pattern
which was in any way simpler to read and more concise than the template
policy one. Since then you've posted a relatively convoluted example, and
wasted a hundred lines or so waltzing around while nitpicking about
irrelevant stuff and avoiding to give a straight answer. If you weren't
avoiding the question by arguing irrelevant points then you wouldn't be
complaining about it. So, do you find the template example harder to
understand? Yes or no? Or will you keep waltzing away, arguing moot points?


Rui Maciel
 
N

Nobody

Is it possible to force a c++ class to implement an interface without
inheriting from the abstract base class? I just want to perform a
compile time check, make sure these methods are implemented, but not
have all the virtual methods, since I've heard that virtual methods have
some performance hit and can't be inlined.

I realize that the performance hit is negligible but why have a
performance hit at all when I'm not really inheriting anything, just
forcing a certain set of methods to be implemented?

Why force certain methods to be implemented? If those methods are being
used, you'll get a compile error if they aren't implemented. If they
aren't being used, what's the point in having them?

Inheriting from an abstract base class doesn't just force certain methods
to be defined. It also causes them to be associated with specific "slots"
in the virtual method table, so that a reference (or pointer) to an
instance to the derived class can be used anywhere that a reference (or
pointer) to an instance of the base class is required.

As to whether the performance hit is negligible: it depends entirely upon
context. The biggest performance issue for virtual methods is that they
tend to inhibit inlining. Sometimes, the difference will be negligible,
other times it can be huge.
 
J

Jorgen Grahn

Is it possible to force a c++ class to implement an interface
without inheriting from the abstract base class? I just want to
perform a compile time check, make sure these methods are implemented,
but not have all the virtual methods, since I've heard that virtual
methods have some performance hit and can't be inlined.

I didn't read the other replies carefully, but do you really have to
do anything at all? C++ is a static language: the compiler (or linker)
*will* tell you if anything is missing.

You could also write a template Foo<T> which can only be
instantiated if T has certain properties.

/Jorgen
 
Ö

Öö Tiib

Blah-blah hundred lines of Rui Maciel I got bored to read.

So, do you find the template example harder to
understand?

I did say it was "too trivial" for me? Also challenged you to write
real strategy pattern? Both those you snipped. Were those hard to
understand?

I also said that the version with interface is, yes, simpler to use
easier to understand and novice-friendlier too. Explained why.
Dunno what you foam there.
 

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,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top