外部 C++ class 以避免包含其头文件
Externing a C++ class to avoid including its header file
我已经为以下 class、libtgbotengine.a
和 extern
编辑了 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.h
。 extern
ing 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 开发人员来说很常见。
这里看起来像:
接口部分:
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*/);
}
实现部分
#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();
...
}
我已经为以下 class、libtgbotengine.a
和 extern
编辑了 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.h
。 extern
ing 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 开发人员来说很常见。
这里看起来像:
接口部分:
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*/); }
实现部分
#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();
...
}