C++ C++;-转发声明和别名(使用或typedef)
我需要实现以下接口C++ C++;-转发声明和别名(使用或typedef),c++,templates,alias,using,forward-declaration,C++,Templates,Alias,Using,Forward Declaration,我需要实现以下接口 struct mutex; struct interface { //... mutex& getMutex(); }; 直觉告诉我,我可以在我的实现中使用使用mutex=specialmutex,但gcc告诉我另外一种情况: error: conflicting declaration ‘using mutex = ’ error: ‘class mutex’ has a previous declaration as ‘class mutex’ 我并没
struct mutex;
struct interface
{
//...
mutex& getMutex();
};
直觉告诉我,我可以在我的实现中使用使用mutex=specialmutex
,但gcc告诉我另外一种情况:
error: conflicting declaration ‘using mutex = ’
error: ‘class mutex’ has a previous declaration as ‘class mutex’
我并没有定义任何东西两次,只是声明了两次,就像在向前声明时一样,所以
界面
的变通方法接口
?使用模板
- 首先,您要说的是,
是一种特定的类类型。然后你会说“哦,等等,mutex
不是它自己的类型,它实际上是另一种类型”。编译器不知道在这种情况下该怎么办mutex
- 用using替换
,它应该可以正常工作(我并没有完全更新C++11的using)struct mutext
- 如果您希望能够支持多个互斥体实现,您可能希望将该接口设置为模板(或者使用一个互斥体抽象接口,该接口实际上决定调用哪个互斥体实现)
struct mutex
告诉编译器互斥体是一种新类型。使用时,您将创建一个类型别名,这意味着它不是一个新类型(正如向编译器承诺的那样),而是一个现有类型的别名
你能做的是: 它确实定义了一个派生自
SpecialMutex
的类型,希望它足够兼容。当然,这是一种可能导致其他问题的新类型。在类似的情况下(使用JNI抽象),下面是我的工作:
JNI文件MyObject.h:
class PlatformObject; // forward declaration
struct MyObject {
int accumulator;
PlatformObject* platformObj;
};
#include <jni.h>
#define PlatformObject _jobject
#include "MyObject.h"
void attach(MyObject& obj, jobject parent) {
obj.platformObj = env->GetObjectField(parent, child_FieldID);
}
void add(MyObject& obj, int k) {
accumulator += k;
env->CallVoidMethod(obj.platformObj, add_MethodID, k);
}
JNI感知文件jniBridge.cpp:
class PlatformObject; // forward declaration
struct MyObject {
int accumulator;
PlatformObject* platformObj;
};
#include <jni.h>
#define PlatformObject _jobject
#include "MyObject.h"
void attach(MyObject& obj, jobject parent) {
obj.platformObj = env->GetObjectField(parent, child_FieldID);
}
void add(MyObject& obj, int k) {
accumulator += k;
env->CallVoidMethod(obj.platformObj, add_MethodID, k);
}
#包括
#定义平台对象_作业对象
#包括“MyObject.h”
无效附加(MyObject和obj、jobject父对象){
obj.platformObj=env->GetObjectField(父、子\u字段ID);
}
无效添加(MyObject和obj,int k){
累加器+=k;
env->CallVoidMethod(obj.platformObj,add_MethodID,k);
}
该选项适用于添加(),但不适用于附加();后者需要额外的静态施法
我认为,在某些情况下,两种方法都有各自的优势 通常,您可以通过将该
SpecialMutex
的存根声明添加到一个头中来解决这个问题。比如:
namespace foreignlib {
namespace foreignsublib {
class ParticularMutex;
}
}
然后在您的常规标题中:
namespace ourlib {
using mutex = foreignlib::foreignsublib::ParticularMutex;
}
这很好,解析和编译速度很快。优点:无论谁读了您的通用头,都知道您的特定
mutex
到底代表什么。缺点:您无法编写互斥体不可知库,以后可以使用using
指令插入一个或另一个互斥体。如果你想要或者需要这样做,C++神想让你使用模板来代替。但是这些都是有代价的…谢谢,关于2:我可能不够明确,但我的意思是“在不修改接口
和转发声明所在的文件的情况下,是否有一个变通方法?”尽管如此,我不明白编译器为什么要在意。我想知道为什么没有一种向前声明的方法说“这个名称代表某种类型。你现在不需要知道确切的定义,但你会在链接时知道它”@ricab编译器关心它,因为这是标准要求的。它是否有用,或者是否应该有某种方法向前声明类型别名,则是另一个问题。坦白地说,模板参数就是这样的:它告诉接口
,稍后您将提供某种类型(或类型别名)。@ricab我用一个可能的解决方案更新了答案,检查它是否对您有效。是的,我想知道标准不包括更通用的fwd声明机制的原因是什么。当使用typedefAlso定义互斥体时,我看不到语义上有任何相关的变化,因此,您的解决方案是有效的。您必须将答案修改为2。从“否”到“是”:(顺便说一句,值得注意的是,gcc4.7不支持以这种方式使用构造函数(我必须使用在线编译器来确认)