2009-10-24 97 views
5

在C++中可以定义不是类成员的转换运算符吗?我知道如何为常规运营商(例如+)做到这一点,但不适用于转换运营商。C++用户定义的转换运算符没有类?

这里是我的用例:我使用一个C库来处理一个PA_Unichar *,其中库定义PA_Unichar是一个16位int。它实际上是一个用UTF-16编码的字符串。我想将它转换为以UTF-8编码的std::string。我把所有的代码转换和准备工作,而我唯一缺少的语法糖,让我写:

PA_Unichar *libOutput = theLibraryFunction(); 
std::string myString = libOutput; 

(通常是在没有临时变量一行)。

另外值得注意:

  • 我知道std::string不会char*定义隐式转换,我知道这是为什么。这里也可能适用同样的理由,但那不是重点。

  • 我确实有一个ustringstd::string的子类,它定义了从PA_Unichar*正确的转换运算符。它的工作原理,但这意味着使用ustring变量而不是std::string然后需要转换到std::string时,我使用这些字符串与其他库。所以这并没有太大的帮助。

  • 使用赋值运算符不起作用,因为那些必须是是类成员。

那么,这可以定义两种类型的你不用管(在我的情况PA_Unichar*std::string),这可能是也可能不是类类型之间的隐式转换运营商?

如果不是什么可能的解决方法?

回答

8

自由功能有什么问题?

std::string convert(PA_Unichar *libOutput); 

std::string myString = convert(theLibraryFunction()); 

编辑回答了评论:

由于DrPizza says:其他人都试图堵塞漏洞通过与那些你所谓的“视觉混乱”显式转换代替他们开辟的隐式转换。

至于临时字符串:只是等待下一个编译器版本。它可能带有右值引用,它的std::string实现将在其上实现移动语义,从而消除副本。我还没有看到比简单升级到新编译器版本更便宜的方法来加速代码。

+0

有什么不对?没有太多,但仍有两件事: - 视觉混乱,当你有数百个毫无意义的调用来转换 - 这个解决方案意味着使用临时的std :: string。这意味着数据总是被复制两次。这可能是也可能不是问题,但不是很令人满意。 – 2009-10-24 14:07:03

+6

大多数编译器会优化额外的拷贝。 – rlbond 2009-10-24 15:09:52

+4

jdmuys> rlbond是对的,RVO在实践中是常见的和真实的。你可能会阅读:http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ – Klaim 2009-10-24 15:26:25

4

我不认为你可以定义“全局”转换运算符。标准说conversion functionsspecial member functions。如果我可以考虑以下语法糖,我会提出以下建议:

struct mystring : public string 
{ 
    mystring(PA_Unichar * utf16_string) 
    { 
     // All string functionality is present in your mystring. 
     // All what you have to do is to write the conversion process. 
     string::operator=("Hello World!"); 
     string::push_back('!'); 
     // any string operation... 
    } 
}; 

请注意,此类的多态行为已损坏。只要你不通过string*类型的指针创建它的一个对象,你就在安全的一面!所以,这个代码是完美的:

mystring str(....); 

如前所述,下面的代码被打破了!

string* str = new mystring(....); 
.... 
delete str; // only deleting "string", but not "mystring" part of the object 
// std::string doesn't define virtual destructor 
5

无论如何,隐式转换是魔鬼。用转换函数调用明确它。

+4

嗯,这取决于。存在隐式转换有意义的实际情况。例如,我通常使用它们来将一种类型转换为另一种类型,这在语义上是另一种类型的子集。例如,如果你有一个“人”类和一个“员工”,我希望'雇员'自动转换为'人',无论后者在哪里。 (当然,另一方面,隐式转换将是一个坏主意。) – Mephane 2011-02-23 10:33:12

+1

我意识到你只是提出了一个假设的例子,但员工作为人的一个子类是一个糟糕的设计和宠物矿。 子类化用于is-a关系。看起来,员工是一个人,但实际上这只是英语语法歧义的一部分。员工不是特殊类型的人,而是一个人可以拥有的角色。这实际上是一种有关系。 – 2012-10-17 14:51:33

3

不,你不能。你可以做的替代方法是在目标类中创建一个转换构造函数(不是你的情况,因为你想转换为std :: string - 除非你派生它)。但我同意其他答案,我认为在这种情况下不推荐使用隐式转换 - 尤其是因为您不是从对象转换而是从指针转换。最好有一个免费的功能,你的代码会更容易理解,下一代程序员继承代码肯定会感谢你。

相关问题