VS2015 的第一步,使用 C++。 Managed/Unmanaged 类 错误。我做错了什么?
First steps with VS2015, using C++. Managed/Unmanaged Classes error. What I'm doing wrong?
我在工作中使用 C++Builder 2006 开发了一个个人项目。
现在我想在家里开发它,使用免费的东西。所以我安装了 Visual Studio 2015(作为第二选择,因为我未能使 Codelite+wxWidgets 工作)并开始了一个新的解决方案/CLR 项目。
但我正在为一个错误而苦苦思索。
这就是我所拥有的;
cSQSequencer class,使用添加->Class 向导创建。
cSQSequencer.h
#pragma once
#include <string>
class cSQSequencer
{
public:
cSQSequencer();
~cSQSequencer();
std::string Name;
void Reset() {
Name="";
};
};
cSQSequencer.cpp
#include "cSQSequencer.h"
cSQSequencer::cSQSequencer()
{
}
cSQSequencer::~cSQSequencer()
{
}
然后我有一个表格,我搜索了一种方法来使用一些向导来添加我的 class,比如添加功能,但我找到了任何东西,所以我手动添加了与我的 [=44] 相关的行=]:
SysExExpMainForm
#pragma once
#include "cSQSequencer.h"
namespace EnsoniqSQKSSysExexporter {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Riepilogo per SysExExpMainForm
/// </summary>
public ref class SysExExpMainForm : public System::Windows::Forms::Form
{
public:
cSQSequencer SQSeq;
SysExExpMainForm(void)
{
InitializeComponent();
//
//TODO: aggiungere qui il codice del costruttore.
//
SQSeq.Reset();
}
protected:
[ all the other code that follows.... ]
错误在行 "cSQSequencer SQSeq;" 中。它说(或多或少,从意大利语翻译回来)"A member of a managed class cannot be a non-managed type"。
我该怎么办?
这是在表单中添加 class 变量的正确方法吗?
或者我应该开始不同类型的项目(但这是我找到的唯一可以添加表格的项目....)
cSQSequencer SQSeq;
您得到的错误消息对于此声明是准确的,使用本机 C++ 对象作为垃圾收集对象的成员,如 Form,是非常非常危险的。非常危险,语言扩展完全禁止它。
垃圾收集对象发生的可能不明显的事情是它们可以在内存中移动。当收集器 compacts 收集通过后堆时会发生这种情况。压缩使堆非常有效,改善了引用的局部性并防止了碎片。
收集器更新任何指向此类移动对象的指针,以将它们重新指向移动的对象。但这只适用于收集器知道的指针。托管指针。不是本机 C++ 对象使用的指针,它们仍将指向此类本机对象曾经存在的位置。现在指着垃圾。在您当前的 cSQSequencer class 中没有太大的危险,我们无论如何都可以看到,但可能不会一直这样。请注意,std::string 成员已经是一个问题,一个模板 class 内部包含指向底层字符串缓冲区的指针。
太危险了,编译器直接禁止了。您必须改用的是指向本机对象的指针或引用。它现在指的是不是从 GC 堆分配的内存,因此是稳定的。所以你需要:
cSQSequencer* SQSeq;
然后跳舞来创造和摧毁它:
MyForm(void) : SQSeq(new cSQSequencer) {
// etc...
}
~MyForm() {
delete SQSeq;
SQSeq = nullptr;
// etc..
}
!MyForm() {
delete SQSeq;
}
请注意 class、!MyForm()
的 finalizer,它确保无论客户端代码是否正确处置对象,都会进行清理。或者换句话说,如果它忘记使用 delete
运算符,那么终结器会确保它无论如何都会发生。在本机 C++ 中没有等效项。从技术上讲,您可以在这种特定情况下忽略它,Form 对象有很好的处理保证,Winforms 运行time 会处理它。但是无论如何都要养成习惯,总有一天你不会失望的。
此代码可能会让您惊呼 "smart pointer"。例如 Nish's CAutoNativePtr and Kenny Kerr's AutoPtr.
另请阅读 this post to know how to properly transmogrify a console app project template to support a UI. There's a lot of 那里弄错了,这也是您不应在析构函数中省略 SQSeq = nullptr 赋值的原因。与原生 C++ 非常不同,析构函数可以 运行 不止一次。只有终结器保证 运行 一次。
我在工作中使用 C++Builder 2006 开发了一个个人项目。 现在我想在家里开发它,使用免费的东西。所以我安装了 Visual Studio 2015(作为第二选择,因为我未能使 Codelite+wxWidgets 工作)并开始了一个新的解决方案/CLR 项目。
但我正在为一个错误而苦苦思索。 这就是我所拥有的;
cSQSequencer class,使用添加->Class 向导创建。
cSQSequencer.h
#pragma once
#include <string>
class cSQSequencer
{
public:
cSQSequencer();
~cSQSequencer();
std::string Name;
void Reset() {
Name="";
};
};
cSQSequencer.cpp
#include "cSQSequencer.h"
cSQSequencer::cSQSequencer()
{
}
cSQSequencer::~cSQSequencer()
{
}
然后我有一个表格,我搜索了一种方法来使用一些向导来添加我的 class,比如添加功能,但我找到了任何东西,所以我手动添加了与我的 [=44] 相关的行=]:
SysExExpMainForm
#pragma once
#include "cSQSequencer.h"
namespace EnsoniqSQKSSysExexporter {
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
/// <summary>
/// Riepilogo per SysExExpMainForm
/// </summary>
public ref class SysExExpMainForm : public System::Windows::Forms::Form
{
public:
cSQSequencer SQSeq;
SysExExpMainForm(void)
{
InitializeComponent();
//
//TODO: aggiungere qui il codice del costruttore.
//
SQSeq.Reset();
}
protected:
[ all the other code that follows.... ]
错误在行 "cSQSequencer SQSeq;" 中。它说(或多或少,从意大利语翻译回来)"A member of a managed class cannot be a non-managed type"。
我该怎么办? 这是在表单中添加 class 变量的正确方法吗? 或者我应该开始不同类型的项目(但这是我找到的唯一可以添加表格的项目....)
cSQSequencer SQSeq;
您得到的错误消息对于此声明是准确的,使用本机 C++ 对象作为垃圾收集对象的成员,如 Form,是非常非常危险的。非常危险,语言扩展完全禁止它。
垃圾收集对象发生的可能不明显的事情是它们可以在内存中移动。当收集器 compacts 收集通过后堆时会发生这种情况。压缩使堆非常有效,改善了引用的局部性并防止了碎片。
收集器更新任何指向此类移动对象的指针,以将它们重新指向移动的对象。但这只适用于收集器知道的指针。托管指针。不是本机 C++ 对象使用的指针,它们仍将指向此类本机对象曾经存在的位置。现在指着垃圾。在您当前的 cSQSequencer class 中没有太大的危险,我们无论如何都可以看到,但可能不会一直这样。请注意,std::string 成员已经是一个问题,一个模板 class 内部包含指向底层字符串缓冲区的指针。
太危险了,编译器直接禁止了。您必须改用的是指向本机对象的指针或引用。它现在指的是不是从 GC 堆分配的内存,因此是稳定的。所以你需要:
cSQSequencer* SQSeq;
然后跳舞来创造和摧毁它:
MyForm(void) : SQSeq(new cSQSequencer) {
// etc...
}
~MyForm() {
delete SQSeq;
SQSeq = nullptr;
// etc..
}
!MyForm() {
delete SQSeq;
}
请注意 class、!MyForm()
的 finalizer,它确保无论客户端代码是否正确处置对象,都会进行清理。或者换句话说,如果它忘记使用 delete
运算符,那么终结器会确保它无论如何都会发生。在本机 C++ 中没有等效项。从技术上讲,您可以在这种特定情况下忽略它,Form 对象有很好的处理保证,Winforms 运行time 会处理它。但是无论如何都要养成习惯,总有一天你不会失望的。
此代码可能会让您惊呼 "smart pointer"。例如 Nish's CAutoNativePtr and Kenny Kerr's AutoPtr.
另请阅读 this post to know how to properly transmogrify a console app project template to support a UI. There's a lot of