【问题标题】:C++ Overload wchar_t assignment operatorC++ 重载 wchar_t 赋值运算符
【发布时间】:2018-12-27 05:24:22
【问题描述】:

我有一个结构体,它有一个 Unicode BSTR 字符串成员,看起来像这样:

struct Foo
{
    wchar_t* Bar;
}

如果我现在想设置该字符串成员,我会这样做

Foo f;
f.Bar = SysAllocString(L"Hello world");

有点冗长。


有什么方法可以“重载”wchar_t 赋值运算符,以便我可以隐藏 SysAllocString 调用并可以简单地编写

Foo f;
f.Bar = L"Hello world";

重载的赋值运算符在哪里处理SysAllocString 调用?

我在想这样的事情(伪代码):

wchar_t* ???::operator=(const wchar_t* rhs)
{
    return SysAllocString(rhs);
}

但我不知道该放什么来代替???,因为我没有上课。

【问题讨论】:

  • 无法重载内置运算符,请改用std::string
  • @VTT 太糟糕了。考虑到我需要使用 BSTR,我会看看 std::string 是否足以完成我的任务。谢谢你的评论:)
  • 我认为BSTR 也有一些现有的包装器
  • 你可以为你的struct Foo重载赋值运算符,所以你可以写f = L"Hello world";
  • @mch 感谢您的建议,但不幸的是,这对我不起作用。我一直在寻找一种适用于任意结构的解决方案,而不必为每个结构本身执行您提出的解决方案。

标签: c++ operator-overloading assignment-operator


【解决方案1】:

wchar_t 是一个内置类型,所以你不能在它上面重载一个操作符。话虽如此,您可以使用std::wstring 代替原始指针,或者定义Foo::operator=(wchar_t*)

struct Foo
{
    wchar_t* Bar;
    Foo& operator=(wchar_t* bar) { Bar = SysAllocString(bar); return *this; }
}

Foo foo;
foo = L"Hello, World!";

来自 cmets:

[U]很幸运,这对我不起作用。我正在寻找一种适用于任意结构的解决方案,而不必为每个结构本身执行您提出的解决方案

您可以在基类中定义该运算符:

struct FooBase
{
    wchar_t* Bar;
    Foo& operator=(wchar_t* bar) { Bar = SysAllocString(bar); return *this; }
}

struct Foo : FooBase { /* whatever */ };
Foo foo;
foo = L"Hello, World!";

...或者你知道,使用标准库中的类型:)

【讨论】:

  • 请注意,您建议的 operator= 存在内存泄漏,因为您需要在 SysAllocString() 新的 Bar 值之前 SysFreeString() 旧的 Bar 值。
  • 默认的复制构造函数、移动构造函数和析构函数都做错了。五/零规则在这里适用。
  • @RemyLebeau 您提到的内存泄漏是“故意的”,因为我打算在 C# 中的指针上调用 SysFreeString。内存将在 C++ 中分配并在 C# 中释放。
  • @ThomasFlinkow 您的问题中没有提到 C#。但即便如此,仅从 C++ 的角度来看,这个类的实现都是各种错误的。当数据仍在 C++ 环境中时,它需要遵循正确的做法。让一种语言在其背后拥有另一种语言的内部数据的做法是不好的做法。在管理动态内存(包括 BSTR)时,COM 有非常具体的规则。 C# 遵循这些规则。你也需要遵守规则。
  • @remi 你关于内存管理的观点是正确的,但是离题了。 OP 提出了How to Ask 中所述的特定问题,并提到内存泄漏很好,但在我看来,这不应该是一个好的答案的重点。我用特定的解决方案回答了特定的问题,正确使用它取决于 OP。你可以给他建议,但如果他们不在乎,他们也不在乎。期间。
【解决方案2】:

首先,如果是BSTR,那么成员应该是:

struct Foo
{
    BSTR Bar;
};

尽管 BSTRwchar_t *a BSTR has different semantics to a string of wchar_t 的 typedef,所以这可以作为自文档。


现在,在 C++ 编程中,OLE 使用类来管理 BSTR 是很正常的。您可以使用现有的,也可以自己滚动。恕我直言,最好使用已经存在的,尽管滚动你自己的可能是一种有趣的学习体验。

我不建议尝试将 BSTR 管理功能拼接到Foo。这导致违反五/零规则。 BSTR 管理应该在其自己的类中自包含,然后您可以将其中一个容器声明为Foo 的成员。


如果您使用的是 Microsoft ATL,那么您可能有 _bstr_tCComBSTR 可用。

在 MinGW-w64 中,_bstr_t 可用于 #include <stdio.h>,然后是 #include <comutil.h> 并与 -loleaut32 链接。

其他一些编译器/框架有自己的 BSTR 包装类。

【讨论】:

    猜你喜欢
    • 2013-03-30
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    • 2012-04-22
    • 2015-06-01
    • 2012-08-17
    • 2011-01-27
    • 2011-05-31
    相关资源
    最近更新 更多