【问题标题】:C++ multiple operator=()C++ 多重运算符=()
【发布时间】:2012-08-09 12:35:54
【问题描述】:

我正在编写一个字符串类。我希望能够分配我的字符串,例如;

a = "foo";
printf(a);
a = "123";
printf(a);
int n = a; // notice str -> int conversion
a = 456; // notice int -> str conversion
printf(a);

我已经分配了我的 operator=() 方法用于字符串到整数的转换。如何声明另一个 operator=() 以便我可以执行反向方法?

当我声明另一个时,它似乎覆盖了之前的。

String::operator const char *() {
    return cpStringBuffer;
}
String::operator const int() {
    return atoi(cpStringBuffer);
}
void String::operator=(const char* s) {
    ResizeBuffer(strlen(s));
    strcpy(cpStringBuffer, s);
}
bool String::operator==(const char* s) {
    return (strcmp(cpStringBuffer, s) != 0);
}

//void String::operator=(int n) {
//  char _cBuffer[33];
//  char* s = itoa(n, _cBuffer, 10);
//  ResizeBuffer(strlen(_cBuffer));
//  strcpy(cpStringBuffer, _cBuffer);
//}

【问题讨论】:

  • 注意:这个“str -> int 转换”和相反,可能不会像你想象的那样做。
  • 这不是家庭作业。我受到启发制作了一个模仿函数式语言字符串的 String 类,因为我厌倦了自己进行转换。
  • 我看不出自动转换与函数式语言有什么关系(当你尝试这样的事情时,Haskell 会尖叫你。)为什么要自己进行转换?有转换功能。
  • @kvanberendonck 是否模仿 功能性 语言?实际上它模仿具有动态类型系统的语言(如果这是您需要的,那么您应该考虑使用另一种语言而不是 C++,因为通常类型安全是他这样做的理由)。
  • @Alderath:它可以通过提供隐式转换来完成,并且在问题中具有当在int 的上下文中使用String 时,将调用上面定义的operator int()是必需的(这里是挥手),但在许多可能不需要它的情况下也是如此(其中int 可以使用

标签: c++ operators implicit-conversion conversion-operator explicit-conversion


【解决方案1】:

单参数构造函数可以充当int->String转换,而所谓的conversion operator执行相反的int->String

class String
{
public:
    String(int)            {} // initialization of String with int
    String& operator=(int) {} // assignment of int to String

    operator int() const {} // String to int
};

但是请注意,这些转换会隐式发生,您很容易被咬。假设您将扩展此类以也接受 std::string 参数和转换

class String
{
public:
    String(int)          {} // int to String
    String(std::string)  {} // std::string to String

    // plus two assignment operators 

    operator int() const       {} // String to int
    operator std::string const {} // String to std::string
};

你会有这两个函数重载

void fun(int)         { // bla }
void fun(std::string) { // bla }

现在尝试致电fun(String())。你会得到一个编译错误,因为有多个 - 同等可行 - 隐式转换。这就是为什么 C++98 允许在单参数构造函数前面使用关键字 explicit,而 C++11 将其扩展到 explicit 转换运算符。

所以你会写:

class String
{
public:
    explicit String(int)          {} // int to String
    explicit operator int() const {} // String to int 
};

隐式转换可能合法的一个示例是智能指针类希望转换为bool 或(如果它们是模板化的)从smart_pointer<Derived> 转换为smart_pointer<Base>

【讨论】:

  • 我尝试了String::String(int n)s=123; 其中s 是字符串的行似乎是无效的转换。它只对构造函数有效吗?
  • 使用构造函数,您可以使用String s(123);String s = 123;,但不能使用String s; s = 123;。后者是赋值,而不是初始化(所以你需要提供更多的赋值运算符)。
  • 啊,谢谢。现在清楚多了。我真正需要做的是分配,抱歉造成误解:)
  • @kvanberendonck 拥有多个赋值运算符或构造函数本身并不坏,糟糕的是拥有多个从String 到所有这些类型的隐式转换运算符。最好制作 explicit 或编写成员函数,如 as_int()
【解决方案2】:

您可能需要转换而不是赋值运算符 运算符——你无法定义额外的赋值 int 的运算符。在您的String 课程中,您可能会写:

class String
{
    //  ...
public:
    String( int i );           //  Converting constructor: int->String
    operator int() const;      //  conversion operator: String->int
    //  ...
};

除了第一个之外,您还可以添加赋值运算符,但它们 除非出于优化原因,通常不需要。

最后,我想你会发现这是个坏主意。如果有目标就好了 是混淆,但除此之外,隐式转换往往会使 代码可读性较差,应避免使用,除非在明显的情况下(例如 Complex 类应该有一个来自 double 的转换构造函数)。 此外,太多的隐式转换会导致歧义 重载决议。

【讨论】:

    【解决方案3】:

    要将您的班级转换为其他班级,您需要conversion operator。像这样的:

    struct Foo
    {
        operator int() const //Foo to int 
        {
            return 10;
        }
    
        operator=(int val) //assign int to Foo
        {
    
        }
    
        operator=(const std::string &s) //assign std::string to Foo
        {
    
        }
    };
    

    【讨论】:

    • 谢谢。那么 operator=() 的目的是什么?另外,如果我需要转换一个整数并将其存储在字符串缓冲区中而不是将我的类转换为另一种值类型,我认为上述方法不起作用。
    • @kvanberendonck: operator=() 用于分配给 Foo
    • @kvanberendonck:第一个(转换)运算符允许您编写integer = string;。第二个(赋值)运算符允许您编写string = integer;
    • 如果我需要使用多个operator=(someType x);怎么办?
    • @kvanberendonck:您可以像任何其他函数一样重载operator=。我在示例中添加了一个运算符
    【解决方案4】:

    要启用int n = a(其中a 是字符串类的对象),您需要一个转换运算符。

    class string {
      public:
        operator int() const { return 23; }
    };
    

    要启用转换为您的类型,您需要一个转换赋值,可能还需要一个转换构造函数。

    class string {
      public:
        string(int i);
        string& operator=(int i);
    };
    

    您还需要const char*char* 等的重载。

    【讨论】:

      猜你喜欢
      • 2012-11-26
      • 2016-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多