【C++】C++/CLI语法大纲,使用 C++ 编写和操作托管代码

C++/CLI 是一种用于在 C++ 和 .NET 环境之间进行互操作的语言扩展,允许开发者使用 C++ 编写和操作托管代码(Managed Code)。以下是 C++/CLI 的语法大纲以及每部分的讲解。


C++/CLI 语法大纲

  1. 托管代码与非托管代码的定义

    • #pragma managed / #pragma unmanaged
    • 托管类型 (ref class, value class, interface)
  2. 托管类型

    • 引用类型 (ref class, ref struct)
    • 值类型 (value class, value struct)
    • 枚举类型 (enum class, enum struct)
  3. 句柄与托管指针

    • 托管指针 ^
    • 原生指针 *
  4. 托管数组

    • 使用 array<Type> 定义托管数组
  5. 托管字符串

    • System::StringString^
  6. 特性(Attributes)

    • 属性标注([Attribute]
  7. .NET 集合和泛型

    • List<T>, Dictionary<TKey, TValue>
  8. 事件与委托

    • 委托 (delegate)
    • 事件 (event)
  9. 可见性

    • 公共 (public)
    • 私有 (private)
    • 内部 (internal)
    • 保护 (protected)
  10. 类型转换

    • safe_cast, dynamic_cast, static_cast
  11. .NET 的托管内存管理

    • 垃圾回收机制
    • gcnew 的使用
  12. CLI 关键字

    • ref, gcnew, nullptr, interface, literal, initonly
  13. 混合代码与互操作

    • 混合模式编程
    • P/Invoke 调用原生 DLL
    • 从托管代码访问非托管代码
  14. CLI 特有的语法

    • property
    • sealed
    • override
    • virtual
    • abstract
  15. 异常处理

    • try/catch 捕获托管异常
    • throw 抛出托管异常

语法详解

1. 托管代码与非托管代码

C++/CLI 支持两种代码模式:

  • 托管代码:运行在 .NET 环境,由 CLR 管理。
  • 非托管代码:传统的 C++ 原生代码。
切换托管/非托管代码
#pragma managed
void ManagedFunction() {
    // 托管代码
}

#pragma unmanaged
void UnmanagedFunction() {
    // 非托管代码
}

2. 托管类型

引用类型 (ref class)
  • 类似于 C# 的引用类型,分配在托管堆中。
ref class MyClass {
public:
    int MyProperty;
};
值类型 (value class)
  • 类似于 C# 的值类型,分配在栈上或结构体中。
value class MyStruct {
public:
    int X, Y;
};
接口 (interface)
  • 类似于 C# 的接口,定义方法约束。
interface class IMyInterface {
    void MyMethod();
};

3. 句柄与托管指针

  • ^:托管对象的句柄。
  • *:原生指针。
示例
ref class ManagedClass {};
ManagedClass^ managedPtr = gcnew ManagedClass();

int* nativePtr = new int(10);

4. 托管数组

使用 array<T> 定义托管数组。

array<int>^ managedArray = gcnew array<int>(10);
managedArray[0] = 42;

5. 托管字符串

System::String 是 .NET 的字符串类型,通过 String^ 使用。

String^ myString = "Hello, C++/CLI!";
Console::WriteLine(myString);

6. 特性(Attributes)

使用方括号标注属性。

[Serializable]
ref class MyClass {};

7. .NET 集合和泛型

C++/CLI 支持 .NET 泛型集合:

using namespace System::Collections::Generic;

List<int>^ myList = gcnew List<int>();
myList->Add(10);

8. 委托与事件

委托
delegate void MyDelegate(int value);
事件
ref class MyClass {
public:
    event MyDelegate^ OnValueChanged;
};

9. 可见性

ref class MyClass {
private:
    int privateField;
protected:
    int protectedField;
public:
    int publicField;
};

10. 类型转换

  • safe_cast: 安全转换(类似于 C# 的 as)。
  • dynamic_cast: 用于托管和非托管之间的动态转换。
  • static_cast: 静态转换。

11. 托管内存管理

  • 使用 gcnew 分配托管堆内存。
ManagedClass^ obj = gcnew ManagedClass();

12. CLI 关键字

  • ref:定义引用类型。
  • gcnew:分配托管堆对象。
  • nullptr:托管对象的空值。
  • literal:常量定义。
  • initonly:只读字段。

13. 混合代码与互操作

调用非托管 DLL
[DllImport("user32.dll")]
extern "C" int MessageBox(IntPtr hWnd, String^ text, String^ caption, unsigned int type);
托管与非托管混合
void CallNativeFunction() {
    #pragma unmanaged
    // 原生 C++ 代码
    #pragma managed
}

14. CLI 特有的语法

属性 (property)
ref class MyClass {
private:
    int value;
public:
    property int Value {
        int get() { return value; }
        void set(int val) { value = val; }
    }
};
sealed
ref class SealedClass sealed {};
override
virtual void MyMethod() override {}
abstract
virtual void MyAbstractMethod() abstract;

15. 异常处理

捕获和抛出托管异常:

try {
    throw gcnew Exception("An error occurred!");
} catch (Exception^ ex) {
    Console::WriteLine(ex->Message);
}

我们可以深入拓展和补充 C++/CLI 语法的应用场景和用法,以便更全面地掌握其功能和特性。


16. C++/CLI 与 C# 的对比

C++/CLI 提供了 .NET 的强大功能,同时保留了 C++ 的灵活性。以下是 C++/CLI 和 C# 之间的一些对比:

功能C++/CLIC#
对象分配使用 gcnew使用 new
空值使用 nullptr使用 null
属性使用 property直接定义 { get; set; }
指针支持托管指针 ^ 和原生指针 *仅支持托管对象
混合代码支持托管和非托管代码切换不支持
C++/CLI 示例
ref class MyClass {
private:
    int value;
public:
    property int Value {
        int get() { return value; }
        void set(int val) { value = val; }
    }
};
C# 示例
public class MyClass {
    public int Value { get; set; }
}

17. C++/CLI 混合模式

C++/CLI 是唯一支持托管代码非托管代码混合的 .NET 语言。这是它最重要的功能之一。

定义与切换

通过 #pragma managed#pragma unmanaged,可以在托管和非托管代码之间切换。

#include <iostream>
#include <string>

void MixedFunction() {
    #pragma unmanaged
    std::string nativeStr = "Hello, Native!";
    std::cout << nativeStr << std::endl;

    #pragma managed
    System::String^ managedStr = "Hello, Managed!";
    System::Console::WriteLine(managedStr);
}

18. 类型互操作

C++/CLI 提供了从托管类型与非托管类型之间的高效转换机制。

托管类型与标准 C++ 类型的转换
  • 使用 marshal_as 进行字符串转换:
#include <msclr/marshal_cppstd.h>
using namespace msclr::interop;

std::string ConvertToNative(String^ managedStr) {
    return marshal_as<std::string>(managedStr);
}

String^ ConvertToManaged(const std::string& nativeStr) {
    return marshal_as<String^>(nativeStr);
}
托管数组与原生数组的互操作
array<int>^ managedArray = gcnew array<int>(5);
int nativeArray[5];

for (int i = 0; i < 5; i++) {
    nativeArray[i] = managedArray[i];  // 或反向赋值
}

19. CLI 特有关键字的详细解释

gcnew
  • 用于在托管堆上分配对象。
  • 示例:
MyClass^ obj = gcnew MyClass();
nullptr
  • 等同于 .NET 的 null,表示托管对象的空值。
  • 示例:
MyClass^ obj = nullptr;
literal
  • 定义编译时常量(类似于 const,但仅适用于托管类型)。
  • 示例:
literal int MaxValue = 100;
initonly
  • 定义只读字段(只能在构造函数中赋值)。
  • 示例:
ref class MyClass {
    initonly int MaxValue;
public:
    MyClass() : MaxValue(100) {}
};

20. 泛型编程

C++/CLI 支持 .NET 的泛型(Generic),例如 List<T>Dictionary<TKey, TValue>

使用泛型集合
using namespace System::Collections::Generic;

List<int>^ intList = gcnew List<int>();
intList->Add(10);
intList->Add(20);

for each (int value in intList) {
    Console::WriteLine(value);
}

21. 委托和事件的应用场景

委托

C++/CLI 的委托与 C# 的 delegate 类似,可用于回调机制。

delegate void MyDelegate(int value);

ref class MyClass {
public:
    MyDelegate^ myDelegate;
    void InvokeDelegate() {
        myDelegate(42);  // 调用委托
    }
};
事件

C++/CLI 的事件使用 event 关键字,适合实现观察者模式。

ref class MyClass {
public:
    event MyDelegate^ OnValueChanged;

    void ChangeValue(int newValue) {
        OnValueChanged(newValue);  // 触发事件
    }
};

22. 异常处理 捕获混合异常

C++/CLI 支持托管异常和非托管异常的处理。

捕获混合异常
try {
    // 非托管代码
    throw std::runtime_error("Native error!");
} catch (std::exception& ex) {
    std::cerr << ex.what() << std::endl;
} catch (System::Exception^ ex) {
    Console::WriteLine(ex->Message);
}

23. 从 C# 调用 C++/CLI

C++/CLI 可以作为一个桥梁,从 C# 调用非托管 C++ 代码。

示例:定义 C++/CLI 类
public ref class MyBridge {
public:
    int Add(int a, int b) {
        return a + b;
    }
};
在 C# 中调用
var bridge = new MyBridge();
int result = bridge.Add(5, 10);
Console.WriteLine(result);

24. 应用场景

C++/CLI 主要适用于以下场景:

  1. 托管与非托管代码的桥梁

    • 用于将传统 C++ 库引入 .NET 项目。
  2. 性能优化

    • 在 .NET 应用中,使用 C++ 编写性能关键的组件。
  3. 与硬件交互

    • 在 .NET 环境中使用低级 C++ 库与硬件通信。
  4. C++/CLI 替代 P/Invoke

    • 比 P/Invoke 更灵活和高效,用于调用非托管代码。

小结

C++/CLI 提供了与 .NET 完美互操作的能力,通过以上语法,开发者可以:

  1. 使用 C++ 编写和管理托管代码。
  2. 与 C# 或 VB.NET 的类库互操作。
  3. 在托管和非托管环境之间高效切换。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值