Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Java makes a clear distinction between class and interface. (I believe C# does also, but I have no experience with it). When writing C++ however there is no language enforced distinction between class and interface.

Consequently I've always viewed interface as a workaround for the lack of multiple inheritance in Java. Making such a distinction feels arbitrary and meaningless in C++.

I've always tended to go with the "write things in the most obvious way" approach, so if in C++ I've got what might be called an interface in Java, e.g.:

class Foo {
public:
  virtual void doStuff() = 0;
  ~Foo() = 0;
};

and I then decided that most implementers of Foo wanted to share some common functionality I would probably write:

class Foo {
public:
  virtual void doStuff() = 0;
  ~Foo() {}
protected:
  // If it needs this to do its thing:
  int internalHelperThing(int);
  // Or if it doesn't need the this pointer:
  static int someOtherHelper(int);
};

Which then makes this not an interface in the Java sense anymore.

Instead C++ has two important concepts, related to the same underlying inheritance problem:

  1. virtual inhertiance
  2. Classes with no member variables can occupy no extra space when used as a base

    "Base class subobjects may have zero size"

    Reference

Of those I try to avoid #1 wherever possible - it's rare to encounter a scenario where that genuinely is the "cleanest" design. #2 is however a subtle, but important difference between my understanding of the term "interface" and the C++ language features. As a result of this I currently (almost) never refer to things as "interfaces" in C++ and talk in terms of base classes and their sizes. I would say that in the context of C++ "interface" is a misnomer.

It has come to my attention though that not many people make such a distinction.

  1. Do I stand to lose anything by allowing (e.g. protected) non-virtual functions to exist within an "interface" in C++? (My feeling is the exactly the opposite - a more natural location for shared code)
  2. Is the term "interface" meaningful in C++ - does it imply only pure virtual or would it be fair to call C++ classes with no member variables an interface still?
share|improve this question
    
C# has the same multiple inheritance of interfaces, single inheritance of implementation as Java, but through the use of generic extension methods, the internalHelperThing can be simulated in almost all cases. –  Sjoerd Feb 13 '12 at 14:30
    
Note that it's bad practice to expose virtual members. –  Klaim Feb 13 '12 at 15:01
    
a public ~Foo() {} in an abstract class is an error under (almost) every circumstance. –  Wolf Jun 6 at 8:27
add comment

4 Answers 4

In C++, the term "interface" has not just one widely accepted definition - so whenever you are going to use it, you should say what you mean exactly - a virtual base class with or without default implementations, a header file, the public members of an arbitrary class and so on.

Concerning your example: in Java (and similar in C#), your code probably would imply a separation of concerns:

interface IFoo {/*  ... */} // here is your interface

class FooBase implements IFoo 
{
     // make default implementations for interface methods
}

class Foo extends FooBase
{
}

In C++, you can do this but you are not forced to. And if you like to call a class an interface if it has no member variables, but contains default implementations for some methods, just do so, but make sure everyone you are talking to knows what you mean.

share|improve this answer
3  
Another possible meaning of "interface", to a C++ programmer, is the public parts of the .h file. –  David Thornley Feb 13 '12 at 15:25
    
What language is your code example? If that is an attempt at being C++ I'm about to cry... –  Qix Dec 20 '12 at 6:32
    
@Qix: keep it easy, read my posting again (it states clearly that the code is in Java), and in case you got >2000 points, you can edit my posting to add the equivalent C++ example code, to make my example more clear. –  Doc Brown Dec 20 '12 at 12:52
    
If that's java then it's still wrong, and no I can't edit it; not enough characters to change. Java doesn't use colons in implementing/extending, which is why I was wondering if it was an attempt at C++... –  Qix Dec 20 '12 at 19:29
    
@Qix: if you find more syntactical issues, you can keep them as a christmas present :-) –  Doc Brown Dec 21 '12 at 8:15
show 1 more comment

It sounds a little like you may have fallen into the trap of confusing the meaning of what it is that an interface is conceptually as both an implementation (the interface - lowercase 'i'), and an abstraction (An Interface - uppercase 'I').

With regards to your examples, your first bit of code is merely a class. While your class has an interface in the sense that it provides methods to enable accesses to it's behavior, it isn't an Interface in the sense of an Interface declaration that provides a layer of abstraction representing a type of behavior that you may want classes to implement. Doc Brown's answer to your post shows you exactly what I am talking about here.

Interfaces are often touted as the "work-around" for languages that don't support multiple inheritance, but I feel that is more of a misconception than a hard truth (and I suspect I may get flamed for stating that!). Interfaces really have nothing to do with multiple inheritance in that they do not require either being inherited, or being an ancestor in order to provide functional compatibility between classes, or implementation abstraction for classes. In fact, they can allow you to effectively do away with inheritance entirely should you wish to implement your code in that way - not that I'd entirely recommend it, but I'm just saying you could do it. So the reality is that regardless of matters of inheritance, Interfaces provide a means by which class-types may be defined, establishing the rules which determine how objects may communicate with each other, thus they allow you to determine the behavior your classes should support without dictating the specific method used to implement that behavior.

Do I stand to lose anything by allowing (e.g. protected) non-virtual functions to exist within an "interface" in C++? (My feeling is the exactly the opposite - a more natural location for shared code)

A pure Interface is meant to be entirely abstract, because it allows the definition a contract of compatibility between classes which may not necessarily have inherited their behavior from a common ancestor. When implemented, you want to make a choice about whether to allow the implementation behavior to be extended in a subclass. If your methods are not virtual, you lose the ability to extend that behavior later should you decide you need create descendant classes. Regardless of whether the implementation is virtual or not, the Interface defines behavioral compatibility in and of itself, while the class provides the implementation of that behavior for the instances that the class represents.

Is the term "interface" meaningful in C++ - does it imply only pure virtual or would it be fair to call C++ classes with no member variables an interface still?

Forgive me, but it's been a long time since I really wrote a serious application in C++. I do recall that Interface is a keyword for the purposes of abstraction as I have described them here. I would not call C++ classes of any sort an Interface, I would instead say the class have an interface within the meanings that I have outlined above. In that sense the term IS meaningful, but that really depends on the context.

share|improve this answer
1  
+1 for the distinction between "having" and "being" an interface. –  Doc Brown Feb 13 '12 at 13:02
add comment

Java interfaces aren't a "workaround," they are a deliberate design decision to avoid some of the problems with multiple inheritance like diamond inheritance, and to encourage design practices that minimize coupling.

Your interface with protected methods is a textbook case of needing to "prefer composition over inheritance." To quote from Sutter and Alexandrescu in the section by that name from their excellent C++ Coding Standards:

Avoid inheritance taxes: Inheritance is the second-tightest coupling relationship in C++, second only to friendship. Tight coupling is undesirable and should be avoided where possible. Therefore, prefer composition to inheritance unless you know that the latter truly benefits your design.

By including your helper functions in your interface, you might be saving a little typing now, but you're introducing coupling that will hurt you down the road. It's almost always better long term to make your helper functions separate and pass in a Foo*.

The STL is a pretty good example of this. As many helper functions as possible are pulled out into <algorithm> instead of being in the container classes. For example, since sort() uses the public container API to do its work, you know you can implement your own sorting algorithm without having to change any STL code. This design enables libraries like boost, which enhance the STL instead of replacing it, without the STL needing to know anything about boost.

share|improve this answer
add comment

Do I stand to lose anything by allowing (e.g. protected) non-virtual functions to exist within an "interface" in C++? (My feeling is the exactly the opposite - a more natural location for shared code)

You'd think that, but putting a protected, non-virtual method in an otherwise abstract class dictates implementation to anyone who writes a subclass. Doing so defeats the purpose of an interface in its pure sense, which is to provide a veneer that hides what's underneath.

This is one of those instances where there isn't a one-size-fits-all answer and you have to use your experience and judgment to make a decision. If you can say with 100% confidence that every possible subclass of your otherwise-fully-virtual class Foo will always need an implementation of the protected method bar(), then Foo is the right place for it. Once you have a subclass Baz that doesn't need bar(), you either have to live with the fact that Baz will have access to code it shouldn't or go through the exercise of rearranging your class hierarchy. The former isn't good practice and the latter can take more time than the few minutes it would have taken to arrange things properly in the first place.

Is the term "interface" meaningful in C++ - does it imply only pure virtual or would it be fair to call C++ classes with no member variables an interface still?

Section 10.4 of the C++ standard makes a passing mention of the use of abstract classes to implement interfaces but doesn't define them formally. The term is meaningful in a general computer science context, and anyone competent should understand that "Foo is an interface for (whatever)" implies some form of abstraction. Those with exposure to languages with defined interface constructs might think pure virtual, but anyone needing to actually work with Foo will look at its definition before proceeding.

share|improve this answer
2  
What's the difference between providing a pure virtual declaration and a declaration plus implementation? In both cases, there has to be an implementation, and baz can always have an implementation like return false; or whatever. If the method doesn't apply to all subclasses, it doesn't belong in the base abstract class in any form. –  David Thornley Feb 13 '12 at 15:27
1  
I think your last sentence says we're on the same page: there's no reason you can't have protected methods in abstract classes, but they shouldn't be any higher in the inheritance tree than absolutely necessary. I just think that if a class has to dummy up an implementation, it's not in the right place in the tree. –  Blrfl Feb 13 '12 at 16:00
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.