Xenoprimate
Xenoprimate

Reputation: 7963

Separating Interface and Implementation in C++

If I have a simple header file:

namespace aNamespace {
    class AClass {
        public:
        AClass();
        ~AClass();

        bool Init();
        void Shutdown();
    };
}

What is the 'correct' way to implement this class in the corresponding CPP file? I can see two options:

Option A

namespace aNamespace {
    class AClass {
        public:
        AClass() { ... }
        ~AClass() { ... }

        bool Init() { ... }
        void Shutdown() { ... }
    };
}

Option B

namespace aNamespace {
    AClass::AClass() { ... }
    AClass::~AClass() { ... }

    bool AClass::Init() { ... }
    void AClass::Shutdown() { ... }
}

The problem I see with Option B is that it's hard to add implementation-specific members to AClass - e.g. what if the implementation requires a std::wstring or so as a storage variable; but that variable isn't defined in the header file?

The reason I'm asking this is because I may wish to have multiple implementations of AClass, and select which one to link according to some external variable (e.g. the target platform or architecture).

Upvotes: 1

Views: 1110

Answers (2)

Ilya Kobelevskiy
Ilya Kobelevskiy

Reputation: 5345

Another option would be to actually make name of each implementation platform specific and have a simple typedef switch in header to control which one is chosen based on target/architecture:

#ifdef target1
typedef AClass Target1ClassImplementation;
#elif  defined target2
typedef AClass Target2ClassImplementation;
#else
#error AClass is not implemented for current target
#endif

If desired, common interface can be encapsulated in a base class implementations derive from. It is less error prone since is more explicit in sense which implementation is for what target, while allows using AClass regardlesss of a platform target outside of header.

Upvotes: 2

egur
egur

Reputation: 7960

B is much better in most cases:

Advantages:

  • Hide implementation details.
  • Less #includes in header files (less exposed dependencies!):
    • Faster builds
    • 2 classes can call each other's functions. Very tricky to do if both are in headers.
    • Changes to implementation do affect other classes (build time).

Disadvantages: - Functions in CPP file do not inline in other modules (across library boundaries)

Optimal: Decide per function which is best. Short one liners to the header and longer ones to the cpp(s). You can have more than 1 source file for the class implementation.

Upvotes: 0

Related Questions