JJB*_*JJB -2 c++ virtual templates abstract-class
我已经在头文件(Environment.h)中声明了以下类,并且我想使超类 FieldAccessor 抽象:
#include <jni.h>
class FieldAccessor {
public:
FieldAccessor(
JNIEnv* env
) {
this->jNIEnv = env;
}
virtual jobject getValue(jobject, jobject) = 0;
protected:
JNIEnv* jNIEnv;
};
template<typename Type>
class PrimitiveFieldAccessor : public FieldAccessor {
public :
PrimitiveFieldAccessor (
JNIEnv* env, const char name[], const char ctorSig[],
Type (JNIEnv::*getFieldValueFunction) (jobject, jfieldID)
);
jobject getValue(jobject, jobject);
private:
jclass type;
jmethodID constructorId;
Type (JNIEnv::*getFieldValueFunction) (jobject, jfieldID);
};
Run Code Online (Sandbox Code Playgroud)
但我得到以下编译错误:
#include <jni.h>
class FieldAccessor {
public:
FieldAccessor(
JNIEnv* env
) {
this->jNIEnv = env;
}
virtual jobject getValue(jobject, jobject) = 0;
protected:
JNIEnv* jNIEnv;
};
template<typename Type>
class PrimitiveFieldAccessor : public FieldAccessor {
public :
PrimitiveFieldAccessor (
JNIEnv* env, const char name[], const char ctorSig[],
Type (JNIEnv::*getFieldValueFunction) (jobject, jfieldID)
);
jobject getValue(jobject, jobject);
private:
jclass type;
jmethodID constructorId;
Type (JNIEnv::*getFieldValueFunction) (jobject, jfieldID);
};
Run Code Online (Sandbox Code Playgroud)
这是实现文件的一部分(DriverFunctionSupplierNative.cpp):
template<typename Type>
PrimitiveFieldAccessor<Type>::PrimitiveFieldAccessor (
JNIEnv* env,
const char name[],
const char ctorSig[],
Type (JNIEnv::*getFieldValueFunction) (jobject, jfieldID)
) : FieldAccessor(env) {
this->jNIEnv = env;
this->type = (jclass)jNIEnv->NewGlobalRef(env->FindClass(name));
this->constructorId = jNIEnv->GetMethodID(this->type, "<init>", ctorSig);
this->getFieldValueFunction = getFieldValueFunction;
}
template<typename Type>
jobject PrimitiveFieldAccessor<Type>::getValue(jobject target, jobject field) {
jfieldID fieldId = jNIEnv->FromReflectedField(field);
return jNIEnv->NewObject(
this->type,
this->constructorId,
this->getFieldValueFunction(target, fieldId)
);
}
Run Code Online (Sandbox Code Playgroud)
编译错误很能描述问题。花时间阅读它们并了解它们的含义:
error: must use '.*' or '->*' to call pointer-to-member function in '...', e.g. ...
Run Code Online (Sandbox Code Playgroud)
现在看看如何尝试调用该函数:
this->callTypeMethodFunction(
...
)
Run Code Online (Sandbox Code Playgroud)
语法如下:
(jNIEnv->*callTypeMethodFunction)(value, this->callTypeMethodId);
Run Code Online (Sandbox Code Playgroud)
同样的事情也适用于指向成员函数调用的另一个指针:
return jNIEnv->NewObject(
this->type,
this->constructorId,
(jNIEnv->*getFieldValueFunction)(target, fieldId)
);
Run Code Online (Sandbox Code Playgroud)
为什么只有在使用虚方法时才会出现编译错误?这是因为模板实例化的工作原理。您没有发布该类将如何实例化,但从症状来看,虚拟函数会提前实例化以构建 vtable,但其他方法(非虚拟)只会在使用时实例化。