Search code examples
c++linuxclassextern

Externing a C++ class to avoid including its header file


I have created a static library for the following class, libtgbotengine.a and externed the class to be used in a different project.

tgbotengine.h

#include <tgbot/tgbot.h>
// Other headers
// ...
class TgBotEngine{
public:
    // Class constructors and functions
    // ...
    void start();
    
private:
    TgBot::Bot m_bot;
    std::vector<TgBot::BotCommand::Ptr> m_commands;
    // Other members
    // ...
}

extern TgBotEngine myTgBotEngine;

In a different project, I want to link libtgbotengine.a with the following cpp file. My goal is to not to include tgbotengine.h. Is externing myTgBotEngine help me achieve this?

project2.cpp

int main(){
    
    myTgBotEngine.start();
    
    return 0;
}

Solution

  • The upcoming modules will probably allow what you want to do. Unfortunately, they are still experimental...

    The only portable way I know to fully hide the implementation details is to split your class between a public interface and a private implementation. This is common to Java developpers.

    Here it would look like:

    1. The interface part:

      The header

       // Other headers
       // ...
       class TgBotEngine {
       public:
           // public functions
           // ...
           virtual void start() = 0;
           static std::unique_ptr<TgBotEngine> build(/*ctor parameters*/);
       }
      

      Source:

       #include <tgbot/tgbotimpl.h>
       #include <tgbot/tgbot.h>
      
       std::unique_ptr<TgBotEngine> TgBotEngine::build(/*ctor parameters*/) {
           return std::make_unique<TgBotEngineImpl>(/*ctor parameters*/);
       }
      
    2. The implementation part

       #include <tgbot/tgbot.h>
       // Other headers
       // ...
       class TgBotEngineImpl: public TgBotEngine {
       public:
           // Class constructors and functions
           // ...
           void start();
      
       private:
           TgBot::Bot m_bot;
           std::vector<TgBot::BotCommand::Ptr> m_commands;
           // Other members
           // ...
       }
      

    You can then use it that way:

    #include "tgb.h"
    #include <memory>
    
    int main() {
        std::unique_ptr<TgBotEngine> engine = TgBotEngine::build(/* ctor parameters*/);
        engine->start();
        ...
    }