我正在尝试采用Curiously Recursive Pattern Template (CRTP) 在我的应用程序中实现一种工厂。
在这篇不错的帖子之后,我开始开发我的 CRTP 版本。通过 CRTP,您只需将工厂产品的新实现声明为好奇模板的子类即可。下面我粘贴了我正在使用的代码的简短示例,它与问题中的示例非常相似。
class abstractProduct {
...
};
template <uint8_t TYPE, typename DERIVED>
class crtp : public abstractProduct{
uint8_t mType;
protected:
crtp() : mType(CRTP_ID){}
public:
enum { _CRTP_ID = TYPE };
static const abstractProduct* get(){
static DERIVED* sInstance = new DERIVED();
return sInstance;
}
static const uint8_t CRTP_ID;
};
template <uint8_t TYPE, typename DERIVED>
const uint8_t crtp<TYPE, DERIVED>::CRTP_ID = Factory::reg(crtp<TYPE, DERIVED>::_CRTP_ID, &crtp<TYPE, DERIVED>::get);
typedef const abstractProduct* (*f_dispenser)(void);
class Factory {
static std::map<uint8_t, f_dispenser>* sDict;
public:
static uint8_t reg(uint8_t shID, f_dispenser dispenser);
static bool has(uint8_t shID);
static const abstractProduct* dispense(uint8_t shID);
};
class sub : public crtp<1, sub>{
friend class crtp<1, sub>;
protected:
sub();
public:
virtual ~sub();
};
如您所见,一旦您声明了类sub
,就应该使用参数创建一个新的 crtp 模板<1, sub>
。模板类crtp
声明了一个const uint8_t CRTP_ID
在 crtp 构造函数中也引用的 static。静态常量变量用 实例化:
template <uint8_t TYPE, typename DERIVED>
const uint8_t crtp<TYPE, DERIVED>::CRTP_ID = Factory::reg(crtp<TYPE, DERIVED>::_CRTP_ID, &crtp<TYPE, DERIVED>::get);
CRTP_ID
应该保证在执行第一条主指令之前被初始化。在类的初始化期间在CRTP_ID
工厂中注册
我目前正在使用 ndk r8d 和 sdk 21.0.1。
现在的问题。如果我使用默认的 gcc 编译器编译我的项目,一切正常,并且 crtp 的子类会自动注册,如果我使用 android 工具链编译我的项目,则永远不会注册子类。
我做错了什么?
编辑
我的 android 应用程序使用NativeActivity完全在 c++ 中实现。我已经定义了一个创建和处理 OpenGLEs 上下文的状态对象。当 Android 通知状态窗口已准备好显示时,它会创建 GL 上下文并加载要渲染的网格。
state.cpp
case APP_CMD_INIT_WINDOW:
LOGI("[state]The window is being shown, get it ready.");
sSurfManager->init(app->window, app->activity->assetManager);
surfacemanager.cpp
int SurfaceManager::init(ANativeWindow* win, AAssetManager* man){
....
this->mModel = GeometryManager::loadModel("cube.ply", man);
}
从文件中GeometryManager::loadModel
加载几何体和材料。对于网格中找到的每种材质,它使用此函数创建一个新的 MaterialData 对象:
static MaterialData* create(aiMaterial* material);
在 MaterialData::create 函数中,工厂被查询以获取适当的着色器来渲染材质。
MaterialData* MaterialData::create(aiMaterial* material){
...
result->setShader(ShaderFactory::dispense(1));
}
我知道这ShaderFactory::dispense(1)
不是获取着色器的正确方法,但我正在使用它来验证着色器是否是在工厂中创建的。
谢谢!