我一直在开发一些DLL实用程序项目,以避免在其他项目中重复代码,以及我还没有尝试过的功能,算法和测试。其中一个项目是C ++ / CLI,这是我还在学习的语言,所以这个问题可能听起来很愚蠢。由于我在C ++ / CLI,F#和C#中有Library Projects,我使用C#控制台应用程序来测试它们。它不能与C ++ / CLI项目一起使用,因此我创建了一个C ++ / CLI控制台测试项目。它从未起作用,当我更改原始DLL C ++的名称时,引用未更新。当我(最终)发现问题时,我更改了.vcxproj文件,使得using指令成为可能,就像一个方法一样,但不是模板类Apont<typename T>
,这是一种内部指针,但是与.NET类型System::IntPtr
不同,使用T*
类型的值而不是void*
。
我还发现(从本网站的帖子中)我必须在项目中使用我想在外面使用的内容,否则这些内容需要在元数据中发出。所以我在静态实用程序中有一个无用的静态方法用于此目的:
static void Funcionalidades()
{
int i = 10;
Apont<int> a2 = Apont<int>(i); // stack
Apont<int> ^a3 = gcnew Apont<int>(i); // heap CLR
}
尽管如此,它不起作用。这是我在C ++ / CLI测试项目中的主要方法:
int main(array<System::String ^> ^args)
{
int y(10);
Apont<int> a = Apont<int>(y);
Console::ReadKey();
return 0;
}
以下是错误(我知道它可以用intellisense错误编译,但无论如何我都会显示它们):
error C2065: 'Apont' : undeclared identifier
error C2062: type 'int' unexpected
IntelliSense: identifier "Apont" is undefined
IntelliSense: type name is not allowed
IntelliSense: expected an expression
为什么这些错误在这里?我怎样才能纠正它们?
我很感激任何回答或回复。
Funcionalidades
方法上,而是发生在测试项目中DLL之外的主方法上。Apont
的更多信息:
Apont
是一个模板(因为T *在内部使用,并且“不允许在通用类型的参数上进行间接”)。Apont
有一个复制构造函数,因此Apont<int> a = Apont<int>(someInt)
应该可以工作; Apont<int> a(someInt)
不起作用; Apont
是某种内部指针;并且我没有发布整个代码,因为它不相关,我必须翻译varibles的名字,它可能有我可以轻易修复的错误,但这只会分散你的注意力。 Apont
你长期以来一直在抱怨的代码:
template<typename T> public ref class Apont sealed : public IDisposable
{
bool eliminado;
T *pointer;
/*void Dispose(bool tudo)
{
if (!eliminado)
{
if (tudo)
{
~Apont();
}
else
{
!Apont();
}
}
}*/
!Apont() // finalizador: limpa os recursos "unmanaged"
{
delete pointer;
pointer = nullptr;
eliminado = true;
}
public:
Apont(T &valor)
{
pointer = &valor;
eliminado = false;
ErroSeNulo = false;
ErroSeEliminado = true;
}
Apont(T &valor, bool erroSeEliminado, bool erroSeNulo)
{
pointer = &valor;
eliminado = false;
ErroSeEliminado = erroSeEliminado;
ErroSeNulo = erroSeNulo;
}
Apont(Apont<T> %outroApont)
{
this->pointer = &outroApont
}
property bool ErroSeEliminado;
property bool ErroSeNulo;
property T Valor
{
T get()
{
if (pointer != nullptr)
return *pointer;
else if (eliminado && ErroSeEliminado)
throw gcnew ObjectDisposedException("O objeto já foi pelo menos parcialmente eliminadao.");
else if (ErroSeNulo)
throw gcnew NullReferenceException();
else
return 0;
}
}
/*
Apont operator ~(/*T valor* /)
{
// este operador tem de ser declarado fora desta classe
}*/
T operator !(/*Apont apont*/)
{
return Valor;
}
void operator =(Apont<T> outroApont)
{
pointer = outroApont;
ErroSeEliminado = outroApont.ErroSeEliminado;
ErroSeNulo = outroApont.ErroSeNulo;
}
template<typename U> void operator =(Apont<U> outroApont)
{
pointer = safe_cast<T>(outroApont.pointer);
ErroSeEliminado = safe_cast<T>(outroApont.ErroSeEliminado);
ErroSeNulo = safe_cast<T>(outroApont.ErroSeNulo);
}
/*
void operator =(T *&outroPointer)
{
pointer = outroPointer;
}
template<typename U> void operator =(U *&outroPointer)
{
pointer = safe_cast<T>(outroPointer);
}*/
void operator =(T *outroPointer)
{
pointer = outroPointer;
}
template<typename U> void operator =(U *outroPointer)
{
pointer = safe_cast<T>(outroPointer);
}
~Apont() // destruidor: limpa todos os recursos
{
this->!Apont();
}
// Error C2605: 'Dispose': this method is reserved within a managed class
// O código será gerado automaticamente a partir do finalizador e do destrutor
};
template<typename T> Apont<T> operator ~(T &valor)
{
return gcnew Apont<T>(valor);
}
答案 0 :(得分:3)
出现的错误通常是缺少类的声明。这通常会发生,然后标题中的代码被标题保护。
这是怎么发生的?
如果你在Funcionalidades中包含Apont标题然后在Apont中包含Funcionalidades标题而不是你遇到麻烦。发生这种情况是因为如果你在包括Funcionalidades之前在你的主要包括Apont,Funcionalidades标题缺少Apont的声明。
然后你第一次包括Apont,它将启用头部保护。然后它将包括Funcionalidades,其中包括Apont。因为标头防护已经启用,Funcionalidades标头将不会有Apont声明。与此同时Apont声明甚至还没有在Apont的相应头文件中开始。而且你在这里,因为这个问题在main中无法编译,因为在库编译时你没有这样的依赖。
如何解决?
在Cpp代码中移动Apont在Funcionalidades实现中的使用,保持头文件没有依赖。
答案 1 :(得分:1)
它只是抱怨它不知道“Apont”。我不知道它是什么,你没有发布它的代码。只是声明它的任意版本:
generic<typename T>
public ref class Apont {
T value;
public:
Apont(T init) : value(init) {}
};
static void Funcionalidades()
{
int i = 10;
Apont<int> a2(i); // stack
Apont<int> ^a3 = gcnew Apont<int>(i); // heap CLR
}
请注意“a2”的更改代码,避免引用类型的复制构造函数。再次在主要:
Apont<int> a(y);
答案 2 :(得分:1)
我必须在项目内部使用我想在
之外使用的内容如果是这样,你有没有在任何地方调用静态函数?机会是未被调用的功能可能会被优化。
答案 3 :(得分:1)
使用名称空间语句会丢失吗?确保在main方法中使用正确的using语句。还要确保添加了一个引用,以便包含main方法的项目引用包含Apont的项目。
答案 4 :(得分:1)
很抱歉花了这么长时间才回复你:我有几点需要帮助解决问题。
- 模板类声明为sealed:这意味着你不能将它用作基类(与模板化类的主要原因相反)。至少它不需要,所以它可能值得删除。
- 其次,更重要的是,在编译时评估C ++模板,因此,由于没有声明指定的实例,因此没有对Apont进行评估,也没有将其编译到DLL中。要启用模板类的特定版本,您可以在UtilCMM.h
文件的末尾添加以下内容:
class template Apont<int>;
class template Apont<float>;
class template Apont<double>;
这是因为在编译时由预处理器扩展C ++模板,就像宏一样,但是只有在编译时才会处理显式使用的版本:这是一个很大的优点和缺点。我一直找到的解决方案(与其他C ++程序员达成共识)是:
如果有其他方法可以实现相同目标,我还没有遇到过它们,并且很想知道,唉这些是模板的局限性。
然后在编译时你应该有三个特定的版本。只需为要包含在DLL中的每种类型添加更多内容。对不起我之前没有发现它,当我看到完整代码时它们都跳出来了。现在如果我可以让项目编译我可以自己尝试更改(我的VS版本不加载你的vcproj文件版本,典型值)。