4

In my company's C++ codebase I see a lot of classes defined like this:

// FooApi.h
class FooApi {
public:
    virtual void someFunction() = 0;
    virtual void someOtherFunction() = 0;
    // etc.
};

// Foo.h
class Foo : public FooApi {
public:
    virtual void someFunction();
    virtual void someOtherFunction();
};

Foo is this only class that inherits from FooApi and functions that take or return pointers to Foo objects use FooApi * instead. It seems to mainly be used for singleton classes.

Is this a common, named way to write C++ code? And what is the point in it? I don't see how having a separate, pure abstract class that just defines the class's interface is useful.

Edit[0]: Sorry, just to clarify, there is only one class deriving from FooApi and no intention to add others later.

Edit[1]: I understand the point of abstraction and inheritance in general but not this particular usage of inheritance.

Shum
  • 1,236
  • 9
  • 22
  • 2
    It's not really a design pattern but rather a core OOP concept – Chris Laplante Mar 26 '14 at 03:08
  • Also see http://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface – Chris Laplante Mar 26 '14 at 03:13
  • 1
    How do you know there is no intention of deriving other classes later? Even if the author has no intention of deriving from `FooApi` himself, he is leaving open the option for others to derive from it. Or leaving the option open for himself, if he decides later that he does in fact want to do that. – Benjamin Lindley Mar 26 '14 at 03:21
  • Because it's used repeatedly throughout a large codebase and all the abstract classes only have one derived class and they are all named after the derived class. ie. there are classes called Foo, FooApi, Bar, BarApi, Quxx, QuxxApi etc. Other parts of the code use inheritance normally and don't follow this naming scheme. – Shum Mar 26 '14 at 03:29
  • The name of this technique is *interface*. – Mark Ransom Mar 26 '14 at 13:27

4 Answers4

3

The only reason that I can see why they would do this is for encapsulation purposes. The point here is that most other code in the code-base only requires inclusion of the "FooApi.h" / "BarApi.h" / "QuxxApi.h" headers. Only the parts of the code that create Foo objects would actually need to include the "Foo.h" header (and link with the object-file containing the definition of the class' functions). And for singletons, the only place where you would normally create a Foo object is in the "Foo.cpp" file (e.g., as a local static variable within a static member function of the Foo class, or something similar).

This is similar to using forward-declarations to avoid including the header that contains the actual class declaration. But when using forward-declarations, you still need to eventually include the header in order to be able to call any of the member functions. But when using this "abstract + actual" class pattern, you don't even need to include the "Foo.h" header to be able to call the member functions of FooApi.

In other words, this pattern provides very strong encapsulation of the Foo class' implementation (and complete declaration). You get roughly the same benefits as from using the Compiler Firewall idiom. Here is another interesting read on those issues.

I don't know the name of that pattern. It is not very common compared to the other two patterns I just mentioned (compiler firewall and forward declarations). This is probably because this method has quite a bit more run-time overhead than the other two methods.

Mikael Persson
  • 18,174
  • 6
  • 36
  • 52
  • `FooApi` is what Java et al. would call an "interface". Your answer provides solid C++ reasoning why separating the interface and the implementation is useful even when there is only a single implementor of the interface. – user4815162342 Jun 01 '14 at 08:06
1

This is for if the code is later added on to. Lets say NewFoo also extends/implements FooApi. All the current infrastructure will work with both Foo and NewFoo.

PlasmaPower
  • 1,864
  • 15
  • 18
1

It's likely that this has been done for the same reason that pImpl ("pointer to implementation idiom", sometimes called "private implementation idiom") is used - to keep private implementation details out of the header, which means common build systems like make that use file timestamps to trigger code recompilation will not rebuild client code when only implementation has changed. Instead, the object containing the new implementation can be linked against existing client object(s), and indeed if the implementation is distributed in a shared object (aka dynamic link library / DLL) the client application can pick up a changed implementation library the next time it runs (or does a dlopen() or equivalent if it's linking at run-time). As well as facilitating distribution of updated implementation, it can reduce rebuilding times allowing a faster edit/test/edit/... cycle.

The cost of this is that implementations have to be accessed through out-of-line virtual dispatch, so there's a performance hit. This is typically insignificant, but if a trivial function like a get-int-member is called millions of times in a performance critical loop it may be of interest - each call can easily be an order of magnitude slower than inlined member access.

What's the "name" for it? Well, if you say you're using an "interface" most people will get the general idea. That term's a bit vague in C++, as some people use it whenever a base class has virtual methods, others expect that the base will be abstract, lack data members and/or private member functions and/or function definitions (other than the virtual destructor's). Expectations around the term "interface" are sometimes - for better or worse - influenced by Java's language keyword, which restricts the interface class to being abstract, containing no static methods or function definitions, with all functions being public, and only const final data members.

None of the well-known Gang of Four Design Patterns correspond to the usage you cite, and while doubtless lots of people have published (web- or otherwise) corresponding "patterns", they're probably not widely enough used (with the same meaning!) to be less confusing than "interface".

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
0

FooApi is a virtual base class, it provides the interface for concrete implementations (Foo).

The point is you can implement functionality in terms of FooApi and create multiple implementations that satisfy its interface and still work with your functionality. You see some advantage when you have multiple descendants - the functionality can work with multiple implementations. One might implement a different type of Foo or for a different platform.

Re-reading my answer, I don't think I should talk about OO ever again.

Rhythmic Fistman
  • 34,352
  • 5
  • 87
  • 159
  • 1
    The `virtual` keyword is not necessary; the methods will be virtual regardless of whether or not the keyword is present. – ApproachingDarknessFish Mar 26 '14 at 03:17
  • @ValekHalfHeart In C++, member functions are non-virtual by default. – Josh Townzen Mar 26 '14 at 03:22
  • I get an error if I try and declare pure functions without virtual. – Rhythmic Fistman Mar 26 '14 at 03:23
  • @JoshTownzen ...unless they are overriding a virtual method. – ApproachingDarknessFish Mar 26 '14 at 03:24
  • @RhythmicFistman The keyword is required whem first declaring the pure virtual functions. I was referring to your second point: once a method has been declared virtual, all method declarations that override it will implicitly be virtual. – ApproachingDarknessFish Mar 26 '14 at 03:26
  • 1
    @ValekHalfHeart Ah. The original post didn't have `virtual` functions in the base class. Those were edited in after Rhythmic Fistman mentioned they were missing. – Josh Townzen Mar 26 '14 at 03:28
  • I was referring to the question in which the functions were pure. – Rhythmic Fistman Mar 26 '14 at 03:29
  • Sorry for all the edits. Yes, everything should be declared virtual. – Shum Mar 26 '14 at 03:32
  • "I've edited my answer..." - almost there - "FooApi is a virtual base class" - it's not... it's just a base class with virtual functions which is a *completely* different thing. Separately, "The point is...create multiple implementations" - the question specifically says this isn't being done, and it's quite possible there's no intention or potential for this to be necessary, and the technique's being done to hide implementation details and/or as a (re)compilation firewall (so a new implementation can be "linked" without a client code recompilation). – Tony Delroy Mar 26 '14 at 04:18
  • Thanks, I should've made the multiple vs singleton mismatch explicit. Re: VBC I had no idea! Objective-C has turned my brain to mush – Rhythmic Fistman Mar 26 '14 at 04:43
  • @RhythmicFistman: lots of people get VBC confused... unsurprising as having pure virtual functions leads naturally to thoughts of virtual base classes, but the correct term there is "abstract base class", and "virtual base classes" are for shared use of a common base object instance by many of a derived class's other bases. – Tony Delroy Mar 26 '14 at 05:58