Interfaces, abstract classes in C++, are not used at all in the code bases I work on regularly. It got me to thinking: "could Go or PHP style interfaces be done in C++?"
Virtual Recap
A virtual function is one that is defined in a class that is intended to be redefined by derived classes. When a base class calls a virtual function, the derived version (if it exists) is called.A key point to make is that virtual functions do NOT need to be defined by a derived class.
To see an example, check out my previous post.
Pure Virtual Goodness
In PHP, you would call these abstract functions. In C++, they are called pure virtual functions. Perhaps a better thing to call them would be purely virtual. I feel like that term makes it more clear to the purpose of this feature. Declare that a function exists as a method on a class but leave the definition for later. It exists purely in a virtual sense.Abstract functions are those that are defined in a lower, base class and implemented by a higher, derived class. Class A provides a prototype for a function but class B, which extends class A, actually implements it.
A pure virtual function is a contract. A class which extends a class with an abstract, pure virtual function must implement it before it can be instantiated. This guarantees that the function will exist somewhere in the class hierarchy. Otherwise, it would be no different than calling a function that has not been defined.
A pure virtual function looks like this:
virtual void Read(std::string& s) = 0;This declares a virtual function Read. The notation of assigning zero to the function designates that the function is purely virtual.
Abstract classes as Interfaces
A class with only pure virtual functions is considered to be an abstract class. Since C++ does not have interfaces in the same way other languages do, abstract classes can fulfill the same role.class Reader { public: virtual void Read(std::string& s) = 0;};The above class is fully abstract. Any classes that extend it will need to implement the method Read.
Or does it?
Compound Interfaces
I am a proponent of small, simple interfaces that can be combined to create ever more complex ones. This is the Interface segregation principle from SOLID design principles. The problem lies in the fact that C++ requires derived classes implement pure virtual functions. Thankfully, there is a way to get around that restriction.Extending a class with the virtual keyword tells the compiler that the derived class will not be implementing the pure virtual function either, making it abstract as well. This allows multiple interfaces to be combined.
class Reader { public: virtual void Read(std::string& s) = 0;}; class Writer { public: virtual void Write(const std::string& s) = 0;}; class ReadWriter : public virtual Reader, public virtual Writer {};Here, the interfaces Reader and Writer get combined into a third abstract class ReadWriter. It too, could add further pure virtual functions if desired.
Implementing an Interface
Implementing the interface is the same as any deriving any class. So, to tie everything together, he's a complete example:#includeThe on caveat is that abstract classes must be some kind of pointer, either as a standard pointer or a reference pointer. This requirement makes sense since it can not be instantiated.#include class Reader { public: virtual void Read(std::string& s) = 0;}; class Writer { public: virtual void Write(const std::string& s) = 0;}; class ReadWriter : public virtual Reader, public virtual Writer {}; class SomeClass: public ReadWriter { std::string buf;public: void Read(std::string& s) override { s = buf; } void Write(const std::string& s) override { buf = s; } }; void readAndWrite(ReadWriter& rw) { rw.Write("Hello"); std::string buf; rw.Read(buf); std::cout << buf << std::endl;} int main() { SomeClass c; readAndWrite(c); return 0;}
Summary
Using pure virtual functions and virtual classes, it is indeed possible to describe behaviour as would be done in other languages with interfaces. Pure virtual functions have a further use in multiple inheritance. To learn more, check out this StackOverflow answer.Happy programming!