我如何制作模板 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,但其他方法(非虚拟)只会被实例化关于使用。