C++ 中的转换运算符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1383606/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:47:51  来源:igfitidea点击:

Conversion Operators in C++

c++conversion-operator

提问by Zuzu

Please help me understand how exactly the conversion operators in C++ work. I have a simple example here which I am trying to understand, though it is not very clear how the conversion actually happens by the compiler.

请帮助我了解 C++ 中的转换运算符究竟是如何工作的。我在这里有一个简单的例子,我试图理解它,尽管不太清楚编译器实际上是如何进行转换的。

class Example{
public:
    Example();
    Example(int val);
    operator unsigned int();
    ~Example(){}
private:
    int itsVal;
};

Example::Example():itsVal(0){}

Example::Example(int val):itsVal(val){}

Example::operator unsigned int (){
    return (itsVal);
}

int main(){
    int theInt = 5;
    Example exObject = theInt; // here 
    Example ctr(5);
    int theInt1 = ctr; // here
    return 0;
}

回答by ChrisW

You can walk through that code with a debugger (and/or put a breakpoint on each of your constructors and operators) to see which of your constructors and operators is being invoked by which lines.

您可以使用调试器遍历该代码(和/或在每个构造函数和运算符上放置断点),以查看哪些构造函数和运算符正在被哪些行调用。

Because you didn't define them explicitly, the compiler also created a hidden/default copy constructor and assignment operator for your class. You can define these explicitly (as follows) if you want to use a debugger to see where/when they are being called.

因为您没有明确定义它们,编译器还为您的类创建了一个隐藏/默认的复制构造函数和赋值运算符。如果您想使用调试器查看调用它们的位置/时间,您可以显式定义它们(如下所示)。

Example::Example(const Example& rhs)
: itsVal(rhs.itsVal)
{}

Example& operator=(const Example& rhs)
{
    if (this != &rhs)
    {
        this->itsVal = rhs.itsVal;
    }
    return *this;
}

回答by Mubeen Iqbal

int main() {
    int theInt = 5;

    /**
     * Constructor "Example(int val)" in effect at the statement below.
     * Same as "Example exObject(theInt);" or "Example exObject = Example(theInt);"
     */
    Example exObject = theInt; // 1

    Example ctr(5);

    /**
     * "operator unsigned int()" in effect at the statement below.
     * What gets assigned is the value returned by "operator unsigned int()".
     */
    int theInt1 = ctr; // 2

    return 0;
}

At statement 1 the constructor Example(int val)is called. Declare it as explicit Example(int val)and you will get a compile time error i.e. no implicit conversion will then be allowed for this constructor.

在语句 1Example(int val)中调用构造函数。将其声明为explicit Example(int val),您将收到编译时错误,即此构造函数将不允许进行隐式转换。

All single argument constructors are called implicitly if the assigned value is of their respective argument type. Using the explicitkeyword before single argument constructors disables implicit constructor calling and hence implicit conversion.

如果分配的值是它们各自的参数类型,则所有单参数构造函数都会被隐式调用。explicit在单参数构造函数之前使用关键字会禁用隐式构造函数调用,从而禁用隐式转换。

If the constructor was declared as explicit i.e. explicit Example(int val)then the following would happen for each statement.

如果构造函数被声明为显式 ie,explicit Example(int val)那么每个语句都会发生以下情况。

Example exObject(theInt); // Compile time error.
Example exObject = theInt; // Compile time error.
Example exObject(Example(theInt)); // Okay!
Example exObject = Example(theInt); // Okay!

Also note that in case of implicit constructor call and hence implicit conversion the assigned value is an rvalue i.e. an un-named object implicitly created using an lvalue (theInt) which tells us that in case of implicit conversion the compiler converts

还要注意,在隐式构造函数调用和隐式转换的情况下,分配的值是一个右值,即一个使用左值(theInt)隐式创建的未命名对象,它告诉我们在隐式转换的情况下编译器会转换

Example exObject = theInt;

to

Example exObject = Example(theInt);

So (in C++11) don't expect the lvalue constructor to be called seeing that you are using an lvalue i.e. a named value theIntfor assignment. What gets called is the rvalue constructor since the assigned value is actually the un-named object created using the lvalue. However, this applies if you have both lvalue and rvalue versions of the constructor.

因此(在 C++11 中)不要期望左值构造函数会被调用,因为您正在使用左值,即theInt分配的命名值。被调用的是右值构造函数,因为分配的值实际上是使用左值创建的未命名对象。但是,如果您同时拥有构造函数的左值和右值版本,则这适用。

At statement 2 operator unsigned int()is called. Simply consider it as a normal function call with a weird name and the fact that it can get called automagically when an implicit conversion happens. The value returned by that function is the value assigned in the expression. And since in you implementation the value returned is an int it correctly gets assigned to int theInt1.

在语句 2 处operator unsigned int()被调用。只需将其视为具有奇怪名称的普通函数调用,并且可以在发生隐式转换时自动调用这一事实。该函数返回的值是在表达式中分配的值。因为在你的实现中,返回的值是一个 int 它正确地被分配给int theInt1.

To be precise operator unsigned int()overloads ()operator which is the cast operator. In your case it's overloaded for inthence whenever an object of Exampleclass is assigned to an intthe implicit type casting from Exampleto inttakes place and hence operator unsigned int()gets called. Therefore,

准确地说,operator unsigned int()重载()运算符是强制转换运算符。在你的情况下,它被重载,int因此每当一个Example类的对象被分配给一个int隐式类型转换从Exampletoint发生并因此operator unsigned int()被调用。所以,

int theInt1 = ctr;

is equivalent to

相当于

int theInt1 = (int)ctr;

回答by Mykola Golubyev

Example exObject = theInt; // implicitly created copy constructor takes place
// object implicitly created from int and then copied
// it is like
Example exObject = Example(theInt);
// so it uses sequence
// Example(int) -> Example(const Example&)
int theInt1 = ctr; // operator int()

If you compiler supports copy constructor optimization and return value optimization you won't notice

如果你的编译器支持复制构造函数优化和返回值优化你不会注意到

Example(const Example&)

execution, but you can declare copy constructor to be private to understand what I am talking about.

执行,但您可以将复制构造函数声明为私有以了解我在说什么。

回答by UncleBens

Example exObject = theInt; // here

This uses implicit conversion of int to Example, effected by the non-explicit constructor which accepts an int.

这使用 int 到 Example 的隐式转换,受接受 int 的非显式构造函数的影响。

This also requires the availability of copy constructor for Example, even though the compiler is allowed to omit copying the instance.

这也需要 Example 的复制构造函数的可用性,即使允许编译器省略复制实例。

int theInt1 = ctr; // here

This uses implicit conversion of Example to unsigned int, provided by the cast operator.

这使用由转换运算符提供的 Example 到 unsigned int 的隐式转换。

Cast operators are normally avoided, since they tend to lead to confusing code, and you can mark single-argument constructors explicit, to disable implicit conversions to your class type. C++0x should add also the possibility to mark conversion operators explicit (so you'd need a static_cast to invoke them? - my compiler doesn't support them and all web resources seem to be concentrating on explicit conversion to bool).

通常避免使用强制转换运算符,因为它们往往会导致代码混乱,您可以将单参数构造函数标记为显式,以禁用对类类型的隐式转换。C++0x 还应该增加将转换运算符标记为显式的可能性(所以你需要一个 static_cast 来调用它们? - 我的编译器不支持它们,而且所有网络资源似乎都专注于显式转换为 bool)。