请帮助我了解究竟是如何转换运营商在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;
}
您可以通过代码调试器行走(和/或将断点上每个建设者和运营商的),看看哪建设者和运营商正在通过线调用。
因为你没有明确定义它们,编译器还为你的类隐藏/默认的拷贝构造函数和赋值运算符。 如果你想使用调试器看到/被调用的时候,他们可以明确地定义这些(如下图)。
Example::Example(const Example& rhs)
: itsVal(rhs.itsVal)
{}
Example& operator=(const Example& rhs)
{
if (this != &rhs)
{
this->itsVal = rhs.itsVal;
}
return *this;
}
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;
}
在声明中1的构造Example(int val)
被调用。 声明为explicit Example(int val)
你会得到一个编译时错误,即没有隐式转换将被允许对这种构造。
所有单参数构造函数被隐式调用如果指定的值是各自的参数类型的。 使用explicit
前一个参数的构造函数的关键字禁用隐式构造函数调用,因此隐式转换。
如果构造函数声明为明确的,即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!
还要注意,在隐含的构造函数调用,因此隐式转换的情况下,分配的值是使用左值(的INT),它告诉我们隐式创建一个右值即未命名的对象,在编译器转换的隐式转换情况
Example exObject = theInt;
至
Example exObject = Example(theInt);
所以(在C ++ 11)不希望被称为左值构造看到你使用的是左值,即一个名为值theInt
用于分配。 什么被调用的是右值的构造函数,因为所分配的值实际上是用左值创建的未命名的对象。 然而,这也适用,如果你有构造函数的两个左值和右值版本。
在声明中2 operator unsigned int()
被调用。 简单地把它作为一个奇怪的名字一般的函数调用,事实上,当隐式转换情况可以得到自动的调用。 由该函数返回的值是在表达式分配值。 而且,由于你执行返回的值是一个int它正确地被分配到int theInt1
。
要精确operator unsigned int()
重载()
操作者即铸造操作者。 在您的情况下,它重载int
因此每当的目的Example
类被分配给一个int
从隐式类型铸造Example
来int
发生,并因此operator unsigned int()
被调用。 因此,
int theInt1 = ctr;
相当于
int theInt1 = (int)ctr;
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()
如果编译器支持拷贝构造函数的优化和返回值优化,你不会注意到
Example(const Example&)
执行,但是你可以声明拷贝构造函数是私有明白我在说什么。
Example exObject = theInt; // here
此方法使用int实施例的隐式转换,通过它接受一个int非显式构造实现。
这也需要复制构造实例的可用性,即使编译器允许省略复制实例。
int theInt1 = ctr; // here
这使用于无符号整型实施例的隐式转换,通过浇铸运营商提供。
铸造运营商通常是可以避免的,因为他们往往会导致混淆代码,你可以标记单参数的构造函数明确,禁止隐式转换为类类型。 的C ++ 0x应该还添加标记转换操作的可能性显式的(所以你需要一个的static_cast调用它们 - 我的编译器不支持他们,所有的网络资源,似乎集中在显式转换为bool)。