一, operator = 与 copy construct function的调用时机区别
class fi {
public:
fi() { i = 2; }
fi( const fi & s )
{
i = s.i * s.i;
}
const fi& operator= ( const fi & s )
{
if ( &s != this ) //一般都要检查是不是给自身赋值,有的情况下给自身赋值会带来一些问题
{
i = s.i;
}
return *this;
}
private:
int i;
};
如下调用:
fi a; //default construct, a.i = 2
fi b = a; //copy construct, not operator = ( b.i = 4 )
b = a; // operator = ( b.i = 2)
结论: 对象被定义的时候,一定是调用 构造函数——无论是缺省构造,还是拷贝构造函数,具体取决于对象从哪里初始化。
最后一个特殊的运算符定义:
前缀的++和后缀的++(前缀的--和后缀的--也一样)
++a 调用 operator++(a)
a++ 调用 operator++(a, int )
以上是对全局定义而言的,如果是定义成了member operator,那调用的就是
++a 调用 operator++()
a++ 调用 operator++( int )
以上的 int 其实在函数中是没有什么用的,就是编译器用来区分这两种形式调用的一个哑元
二,自动类型转换
1,特殊类型的构造函数。
假设有如下的函数f,以及one和two类定义。
class one{
public:
one(){};
};
class two {
public:
two( const one&){}
};
one o1;
two o2;
void f( two );
那么f( o2 )调用肯定没有问题。f( o1 )呢?也没有,因为编译器会自动将one转换成two( 由于two( const one &)构造函数的存在 ),这就是自动转换之一。
如何组织这种自动转换?只要将 two( const one&){} 改成 explicit two( const one&){}即可,这样就可以了,那么调用只能改为,f( two(o1) ) ,这样我们手动做了编译器的工作了,因为编译被告知:不能使用那个构造函数执行任何的自动转换。
那么除了上面的这种特殊构造函数外,还有没有另外的一个方法呢?这就是运算符重载。
2,运算符重载。
自动类型转换的第2种方法就是运算符重载。通过 operator 后面跟上要转换的类型,就可以将当前类型转换为所想要的。这种方法非常独特: 这个成员函数的运算符重载没有指定返回类型,它的返回类型就是:我们希望重载的运算符的名字。
class two {
public:
// two( const one&){}
};
class one{
public:
one(){};
operator two() const { return two(); }
};
void f( two );
总结:
这两种转换的区别:
构造函数: 目的类进行转换。
运算符重载: 原类进行转换,并且可以实现从用户自定义类型向内置类型转换。例如:
class three{
public:
three():i(0){}
three( int I ): i( I ){}
operator int () const { return i; }
private:
int i;
};
void fun1( int i );
fun1( 100 );
three obj( 90 );
fun1( obj ); //合法,可以向内置类型转换