简体   繁体   English

如何在以下c ++代码中基于返回类型进行运算符重载解析

[英]how does operator overload resolution work based on return type in the following code of c++

I know that there is no legal overload based on return type in C++; 我知道在C ++中没有基于返回类型的合法重载; ie you cannot do something like: 即您不能做类似的事情:

int operator ++ getOwner();
char operator ++ getOwner();

However, I stumbled upon the following: 但是,我偶然发现了以下内容:

https://stackoverflow.com/a/9569120/1376317 https://stackoverflow.com/a/9569120/1376317

class Proxy
{
    My const* myOwner;
public:
    Proxy( My const* owner ) : myOwner( owner ) {}
    operator int() const
    {
        return myOwner->getInt();
    }
    operator char() const
    {
        return myOwner->getChar();
    }
};

My question is how does operator overload work in this configuration. 我的问题是在这种配置下操作员重载如何工作。 How do you call this in your main.cpp to get this kind of overloading. 您如何在main.cpp中调用它来获得这种重载。 How does the compiler deduce , how to call the right overload? 编译器如何演绎,如何调用正确的重载?

My question is how does operator overload work in this configuration. 我的问题是在这种配置下操作员重载如何工作。

These operators provide implicit conversions . 这些运算符提供隐式转换 That means that this class can be used in many contexts where an int or char is expected, and will use these operators to provide the expected value. 这意味着该类可以在需要intchar许多上下文中使用,并将使用这些运算符提供期望的值。

How do you call this in your main.cpp to get this kind of overloading. 您如何在main.cpp中调用它来获得这种重载。

Here are a few examples of implicit conversions: 以下是一些隐式转换的示例:

Proxy p = whatever();
int i = p;   // convert to int
char c = p;  // convert to char
long l = p;  // ERROR: ambiguous

void f(int);
f(p);        // convert to int

void g(int);
void g(char);
g(p);        // ERROR: ambiguous

You can also request explicit conversions using the usual cast notations: 您还可以使用通常的转换符号请求显式转换:

long l = static_cast<int>(p);  // convert to int, then to long
g((char)p);                    // convert to char

How does the compiler deduce , how to call the right overload? 编译器如何演绎,如何调用正确的重载?

Whenever there's a type mismatch, the compiler looks for a conversion sequence. 只要类型不匹配,编译器就会寻找转换序列。 The rules are quite complicated, but basically the sequence can include at most one user-defined conversion (using either an operator like this, or a converting construction), as well as standard conversions such as int to long . 规则很复杂,但是基本上,该序列最多可以包含一个用户定义的转换 (使用这样的运算符或转换构造),以及标准转换,例如intlong

This is sometimes called the Return Type Resolver idiom or "overload on return type". 有时称为“ 返回类型解析器”惯用语或“返回类型超载”。 The conversion operator to call is selected thanks to the context of use where an implicit conversion is needed (for example based on the type of an object to initialize or assign to). 由于需要隐式转换(例如,基于要初始化或分配给的对象的类型)的使用上下文,因此选择了要调用的转换运算符。 For example: 例如:

#include <stdio.h>

class RtR {
public:
    operator int() const
    {
        puts("operator int()");
        return 42;
    }
    operator double() const
    {
        puts("operator double()");
        return 3.14;
    }
};

void f(int) {}

int main()
{
    RtR x;
    int i = x; // or int i = RtR();
    double d = x;
    f(x);
}

output: 输出:

operator int()
operator double()
operator int()

See it live . 现场观看

In 13.1 Overloadable declarations: 在13.1可重载声明中:

Function declarations that differ only in the return type cannot be overloaded. 只能重载返回类型不同的函数声明。 [ Note: ... It does not apply to sets of functions fabricated as a result of name lookup (eg, because of using-directives) or overload resolution (eg, for operator functions) ... ] [注意:...不适用于因名称查找(例如,由于使用指令)或重载解析(例如,用于操作员功能)而构造的功能集...]

Hence this is valid: 因此,这是有效的:

struct X {
    // Conversion function:
    operator int () { return 1; }
    operator double () { return 2; }
};

In addition (not relating directly to the question): 另外(与问题无直接关系):

struct Y
{
    // Operator (Function call):
    int operator () (int) { return 1; }
    double operator () (double) { return 2; }

    // Operator (Subscripting):
    int operator [] (int) { return 1; }
    double operator [] (double) { return 2; }

    // Operator (Shift):
    int operator << (int) { return 1; }
    double operator << (double) { return 2; }

    // and more ...
};

上面的代码用于operator类型转换,并提供了一种隐式方式将Proxy类型转换为intchar

The compiler "knows" based on the context of the conversion calls, for instance: 编译器根据转换调用的上下文“知道”,例如:

Proxy p;

// p_int will be set equal to p.my_owner->getInt()
int p_int = p;

// p_char will be set equal to p.my_owner->getChar()
char p_char = p;

The fact that it's a proxy is irrelevant; 它是代理的事实无关紧要; the same thing works for any class. 相同的东西适用于任何班级。 Those are conversion operators, and the compiler does select the right version based on how it's used in the calling code. 这些是转换运算符,编译器根据调用代码中的用法选择正确的版本。

struct S {
    operator int() const { return 1; }
    operator double() const { return 2.0; }
};

int main() {
    S s;
    int i = s;
    double d = s;
    std::cout << i << ' ' << d << '\n';
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM