You are using the PIMPL idiom. Another way to hide the implementation is to use interfaces, i.e. Abstract base class and factory function:
interface.hpp:
class interface{ public: virtual ~interface(){} virtual void some_method() = 0; };
interface.cpp:
#include "interface.hpp" #include "engine.hpp" class concrete : public interface{ public: virtual void some_method() override { } private: engine eng; }; some_smart_pointer<interface> create(){ return new concrete; }
main.cpp
#include "interface.hpp" int main() { auto interface = create(); interface->some_method(); return 0; }
The downside here is that you have to dynamically allocate interface instead of engine .
Read more about PIMPL and interfaces here and here.
EDIT:
Based on the STL containers and Howard Hinnant stack allocator , a third way to avoid variables in free storage could be:
interface.hpp:
class interface{ public: interface(); ~interface();
interface.cpp:
#include "interface.hpp" #include "engine.hpp" #include "short_alloc.h" #include <map> namespace { std::map< interface*, engine, std::default_order<interface*>, // use a stack allocator of 200 bytes short_alloc<std::pair<interface*, engine>, 200> > engines; } interface::interface(): eng(&engines[this]) // operator[] implicitly creates an instance and returns a reference to it // the pointer gets the address { } interface::~interface() { // destroy the instance engines.erase(this); }
wasthishelpful
source share