外部 C++ class 以避免包含其头文件

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

我已经为以下 class、libtgbotengine.aextern 编辑了 class 的静态库以用于不同的项目。

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;

在另一个项目中,我想 link libtgbotengine.a 使用以下 cpp 文件。我的目标是不包括 tgbotengine.hexterning myTgBotEngine 能帮我实现这个目标吗?

project2.cpp

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

恕我直言:你想做的事是不可能的。

您的库的头文件就像是您 class 的蓝图。

让我们扩展 TgBotEngine 的例子:

class TgBotEngine{
public:
    // ...
    virtual void someMethod() = 0;    // for this example this is the first method
    virtual void start() = 0;         // for this example this is the second method
    virtual void anotherMethod() = 0; // for this example this is the third method
    // ...
}

我们假设 TgBotEngine 是一个纯虚拟 class。在您提供头文件之前,编译器不知道哪个:)

像这样调用它:

void callBot(TgBotEngine& tge)
{
    tge.start();
}

编译器对这一行所做的事情:tge.start(); 是调用 TgBotEngine 的第二个方法,该方法将位于索引 1 处。将其想象成这样的伪代码:myTgBotEngine.[1]()

要确定您的方法在 class 中的位置,您必须提供头文件。

即将到来的 modules 可能会允许你做你想做的事。不幸的是,它们仍处于试验阶段...

我知道完全隐藏实现细节的唯一可移植方法是将 class 拆分为 public 接口和 private 实现。这对 Java 开发人员来说很常见。

这里看起来像:

  1. 接口部分:

    header

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

    来源:

     #include <tgbot/tgbotimpl.h>
     #include <tgbot/tgbot.h>
    
     std::unique_ptr<TgBotEngine> TgBotEngine::build(/*ctor parameters*/) {
         return std::make_unique<TgBotEngineImpl>(/*ctor parameters*/);
     }
    
  2. 实现部分

     #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
         // ...
     }
    

然后您可以这样使用它:

#include "tgb.h"
#include <memory>

int main() {
    std::unique_ptr<TgBotEngine> engine = TgBotEngine::build(/* ctor parameters*/);
    engine->start();
    ...
}