【问题标题】:Implicit Conversion Operator for Class Objects to Strings [duplicate]类对象到字符串的隐式转换运算符
【发布时间】:2020-09-15 07:39:37
【问题描述】:

我正在学习有关隐式转换运算符的更多信息,并且我注意到字符串的隐式用户定义转换有些奇怪。下面是代码。

#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

class A {
    public:
        A() {
            *value = "YIKERS";
        } 
        operator string&() {
            return *this->value;
        }
        string* value;
};


int main() {
    A abc;
    cout << abc << endl; 
// compile error: invalid operands to binary expression ('std::__1::ostream' (aka
// 'basic_ostream<char>') and 'A')
    return 0;
}

关于我为什么会收到此编译错误的任何想法?我在想这可能意味着该对象没有被隐式转换为字符串?如果是这样,为什么不呢?有没有办法解决这个问题?转换运算符非常适用于其他数据类型,如 int、float、char 等。

【问题讨论】:

  • ot:您应该存储 std::string 而不是指向字符串的指针。它与您的问题无关,但它会使您的代码不那么“令人惊讶”
  • 即使编译了代码,它仍然无法正常工作,因为A 构造函数正在取消引用未初始化的指针,导致未定义的行为
  • @RemyLebeau 为什么它是一个无效的指针?
  • “我的代码要求成员变量是一个指针”我强烈怀疑它需要是一个原始指针。
  • @MAGEPAC "为什么它是一个无效的指针?" - 因为在取消引用它以将数据分配给内存之前,您没有为指针分配有效的内存地址地址。鉴于您正在尝试,您需要分配一个有效的string 对象并将其内存地址分配给指针。为此使用new。然后确保A 跟在Rule of 3 后面,确保string 对象得到妥善管理。

标签: c++ operator-overloading implicit-conversion conversion-operator


【解决方案1】:

首先,我认为您没有按预期使用std::string value。这会导致另一个编译错误(至少在 gcc 10.2 上)。 似乎您想要一个字符串,而您正在使用指向字符串的指针。 这可以通过将string* value 替换为string valueoperator string&amp;() 替换为operator string()*value = "YIKERS' 替换为value = "YIKERS" 来解决。对于最后一个,您可能还需要检查初始化列表。

关于当前编译错误:

编译错误是由代码cout &lt;&lt; abc 尝试在abc 上使用运算符abc 是A 类型的对象。但是,您没有重载此运算符。 在您的示例中,这可能类似于

friend std::ostream &operator<<(std::ostream &output, const A &a ) 
{ 
    output << a.value;
    return output;            
}

即使您将用户定义的转换为std::string,您仍然会收到编译时错误。这个链接解释得比我想象的要好Why cannot use cout with user-defined conversion to std::string?

这就是我对上面链接的解释的理解:

string 标头为operator&lt;&lt;std::basic_ostream 定义了以下重载:

template <class CharT, class Traits, class Allocator>
std::basic_ostream<CharT, Traits>&
    operator<<(std::basic_ostream<CharT, Traits>& os,
               const std::basic_string<CharT, Traits, Allocator>& str);

另外,std::string 实际上是 std::basic_string&lt;char&gt; 的 typedef。

但是,如果转换是隐式的,则以下规则生效:

类型推导不考虑隐式转换(除了类型 上面列出的调整):这就是重载解决的工作, 稍后会发生。

因此,编译器无法从 A 推导出函数的第二个参数(例如 const std::basic_string&lt;CharT, Traits, Allocator&gt;&amp; str)。但是,它可以为string 推断它,因此您可以像static_cast&lt;string&gt;(abc) 一样将abc 显式转换为string,这样就可以了。

【讨论】:

  • 我明白了。看来我将不得不改变我的设计。如果我们隐式定义转换运算符,则 operatoroperator string&() 更改为operator string(),那么它将不支持应该返回左值的运算符,例如混合赋值运算符*=++ 等。
  • @TwoOfDiamonds operator&lt;&lt; 被重载以接受 const string&amp; 作为输入。很明显,OP 打算将 A 对象隐式转换为 string 以便调用重载。如果您扩展它以解释为什么实际上没有按预期调用该重载,则此答案会更有用。
  • @MAGEPAC "如果我们隐式定义转换运算符,则运算符 - 不,它不应该是自动的。这不是运算符重载的工作方式.
  • @RemyLebeau 也许我的措辞不正确。我的意思是 operator&lt;&lt; 应该仍然可以工作,因为它支持 string 对象,该对象具有隐式转换运算符。
  • 那么解决办法是根据需要手动声明算子重载?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-15
  • 1970-01-01
  • 2013-08-25
  • 2020-02-02
  • 2014-09-17
  • 1970-01-01
相关资源
最近更新 更多