我如何制作模板 class 的 superclass 摘要?
How can I make a superclass of a template class abstract?
我已经在头文件 (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);
};
但是我得到以下编译错误:
F:/Shared/Workspaces/Projects/JNI/src/DriverFunctionSupplierNative.cpp: In instantiation of '_jobject* PrimitiveFieldAccessor<Type>::getValue(jobject, jobject) [with Type = long int; jobject = _jobject*]':
F:/Shared/Workspaces/Projects/JNI/src/Environment.h:73:11: required from here
F:/Shared/Workspaces/Projects/JNI/src/DriverFunctionSupplierNative.cpp:80:2: error: must use '.*' or '->*' to call pointer-to-member function in '((PrimitiveFieldAccessor<long int>*)this)->PrimitiveFieldAccessor<long int>::getFieldValueFunction (...)', e.g. '(... ->* ((PrimitiveFieldAccessor<long int>*)this)->PrimitiveFieldAccessor<long int>::getFieldValueFunction) (...)'
这是一段实现文件(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)
);
}
编译错误很能说明问题。花时间阅读它们并了解它们的含义:
error: must use '.*' or '->*' to call pointer-to-member function in '...', e.g. ...
现在看看你是如何尝试调用函数的:
this->callTypeMethodFunction(
...
)
语法是这样的:
(jNIEnv->*callTypeMethodFunction)(value, this->callTypeMethodId);
同样的事情适用于指向成员函数调用的另一个指针:
return jNIEnv->NewObject(
this->type,
this->constructorId,
(jNIEnv->*getFieldValueFunction)(target, fieldId)
);
现在为什么只有当你有虚拟方法时才会出现编译错误?这是因为模板实例化的工作方式。你没有post如何实例化class,但看症状是虚拟函数提前实例化以构建vtable,但其他方法(非虚拟)只会被实例化关于使用。
我已经在头文件 (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);
};
但是我得到以下编译错误:
F:/Shared/Workspaces/Projects/JNI/src/DriverFunctionSupplierNative.cpp: In instantiation of '_jobject* PrimitiveFieldAccessor<Type>::getValue(jobject, jobject) [with Type = long int; jobject = _jobject*]':
F:/Shared/Workspaces/Projects/JNI/src/Environment.h:73:11: required from here
F:/Shared/Workspaces/Projects/JNI/src/DriverFunctionSupplierNative.cpp:80:2: error: must use '.*' or '->*' to call pointer-to-member function in '((PrimitiveFieldAccessor<long int>*)this)->PrimitiveFieldAccessor<long int>::getFieldValueFunction (...)', e.g. '(... ->* ((PrimitiveFieldAccessor<long int>*)this)->PrimitiveFieldAccessor<long int>::getFieldValueFunction) (...)'
这是一段实现文件(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)
);
}
编译错误很能说明问题。花时间阅读它们并了解它们的含义:
error: must use '.*' or '->*' to call pointer-to-member function in '...', e.g. ...
现在看看你是如何尝试调用函数的:
this->callTypeMethodFunction(
...
)
语法是这样的:
(jNIEnv->*callTypeMethodFunction)(value, this->callTypeMethodId);
同样的事情适用于指向成员函数调用的另一个指针:
return jNIEnv->NewObject(
this->type,
this->constructorId,
(jNIEnv->*getFieldValueFunction)(target, fieldId)
);
现在为什么只有当你有虚拟方法时才会出现编译错误?这是因为模板实例化的工作方式。你没有post如何实例化class,但看症状是虚拟函数提前实例化以构建vtable,但其他方法(非虚拟)只会被实例化关于使用。