【问题标题】:Extension of c++ constructor/typedefc++构造函数/typedef的扩展
【发布时间】:2016-01-15 10:35:38
【问题描述】:

Borland C++Builder 中 C++ 构造函数的扩展。

我有一些代码可以连接UnicodeString 值(以前是AnsiString)。

UnicodeString string="test1";
Variant v1="test";
string = string + UnicodeString(v1);

[bcc32 错误] myTest.cpp(154): E2015 Ambiguity between 'System::UnicodeString::UnicodeString(const System::UnicodeString &) at c:\program files (x86)\embarcadero\studio\17.0\include\windows\rtl\ustring.h:86' 和 'System::UnicodeString::UnicodeString(const wchar_t *) at c:\program files (x86)\embarcadero\studio\17.0\include\windows\rtl\ustring.h:89'

现在,问题是Variant 是模棱两可的,编译器会抱怨这种模棱两可(很公平)。

如果我将直接转换添加到string,它可以正常工作。

string = string + UnicodeString(v1.As<UnicodeString>());

问题是我的代码很大,而且有成千上万个这样的代码。我想介绍一个新的显式 typedef 或宏来执行此操作:

给定参数 v1 是 Variant,它执行而不是这个:

UnicodeString(v1)

它改为执行此操作:

UnicodeString(v1.As<UnicodeString>())

我知道这可以通过添加 UnicodeString(Variant) 以某种方式(不确定如何)扩展 UnicodeString 的构造函数或 typedef 来实现 (或宏?)。

附言。 UnicodeString是系统类,不能直接修改。

PS1。 AnsiString 也有同样的问题(甚至更多的代码片段)。制作函数不起作用:(。对于AnsiString,它不起作用:(。

系统头文件(sysmac.h)中AnsiString的定义:

typedef AnsiStringT<0> AnsiString;

例子:

AnsiString myTest::AnsiString(Variant v)
{
    return "";
}

[bcc32 错误] .cpp(122): E2235 成员函数必须被调用或其地址被占用

【问题讨论】:

  • 只定义一个函数
  • 对于 AnsiString 它不起作用 :(。系统头文件 (sysmac.h) 中的定义: typedef AnsiStringT AnsiString; 示例: AnsiString myTest::AnsiString(Variant v) { return ""; } [bcc32 错误] .cpp(122): E2235 成员函数必须被调用或其地址被占用
  • 不要将您的函数命名为AnsiString(),而是将其命名为AsAnsiString()。让它成为你的类的成员是没有意义的(除非你将它定义为static),因为它没有访问该类的任何成员。为什么是return "" 而不是return v.As&lt;AnsiString&gt;()?

标签: c++ error-handling typeof unicode-string


【解决方案1】:

我认为您尝试执行的操作会严重损害代码的可读性。更改内置类的构造函数(即使有可能)肯定会让任何阅读您的代码的人感到惊讶。更好的解决方案是在某处添加一个函数

void addVariantToUnicodeString(UnicodeString& string, Variant& v){
    string = string + UnicodeString(v1.As<UnicodeString>());
}

或类似的东西(可能使用模板)。现在只需相应地替换您的代码。作为一个额外的好处,您的代码现在将清楚地说明它正在做什么,而不是简单地执行晦涩的字符串操作。当然,您也可以构建自己的字符串管理类来提供您需要的功能。这在一定程度上取决于您的问题的复杂性和程度。

【讨论】:

  • 定义一个自定义的全局operator+() 怎么样? UnicodeString operator+(const UnicodeString&amp; string, const Variant&amp; v) { return string + v1.As&lt;UnicodeString&gt;(); }
【解决方案2】:

PS。 UnicodeString是系统类,不能直接修改。

在 C++Builder 中,UnicodeString 和 AnsiString/AnsiStringT 与其他类一样(尽管您不能从它们派生自定义后代,因为它们被标记为 __declspec(delphireturn) 以防止这种情况发生)。 UnicodeString 在 ustring.h 中声明,AnsiStringT 在 dstring.h 中声明,AnsiString 在 sysmac.h 中声明(正如您已经指出的那样)。您可以简单地编辑 ustring.h 和 dstring.h 以将自定义构造函数添加到这些类,例如:

ustring.h

namespace System
{
  ...
  class RTL_DELPHIRETURN UnicodeString
  {
  ...
  public:
    ...
    explicit __fastcall UnicodeString(const Variant &src) : Data(0) { *this = src.As<UnicodeString>(); }
    ...
  };
  ...
}

dstring.h

namespace System
{
  ...
  template <unsigned short CP>
  class RTL_DELPHIRETURN AnsiStringT : public AnsiStringBase
  {
  ...
  public:
    ...
    explicit __fastcall AnsiStringT(const Variant &src) : AnsiStringBase() { *this = src.As< AnsiString<T> >();}
  };
  ...
}

替代方法是在您自己的代码中定义一个自定义operator+(),以将Variant 连接到UnicodeString:

UnicodeString operator+(const UnicodeString& s, const Variant& v)
{
    return s + v.As<UnicodeString>();
} 

但这需要像这样更改语句:

string = string + UnicodeString(v1);

改为:

string = string + v1;

如果您要费力地进行更改,那么您可以忘记上面的所有内容并改为执行此操作(就像您一开始就应该做的那样):

string = string + v1.As<UnicodeString>();

【讨论】:

    猜你喜欢
    • 2014-04-18
    • 2012-01-09
    • 1970-01-01
    • 1970-01-01
    • 2013-05-29
    • 1970-01-01
    • 2013-11-15
    • 2019-01-07
    • 2014-05-29
    相关资源
    最近更新 更多