Ara*_*raK 38 c++ conversion-operator
考虑这个简单的例子:
template <class Type>
class smartref {
public:
smartref() : data(new Type) { }
operator Type&(){ return *data; }
private:
Type* data;
};
class person {
public:
void think() { std::cout << "I am thinking"; }
};
int main() {
smartref<person> p;
p.think(); // why does not the compiler try substituting Type&?
}
Run Code Online (Sandbox Code Playgroud)
转换运算符如何在C++中工作?(即)编译器何时尝试替换转换运算符后定义的类型?
Joh*_*itb 53
使用转换函数但未使用转换函数的一些随机情况如下.
首先,请注意转换函数从不用于转换为相同的类类型或基类类型.
参数传递期间的转换将使用复制初始化的规则.这些规则只考虑任何转换函数,无论是否转换为引用.
struct B { };
struct A {
operator B() { return B(); }
};
void f(B);
int main() { f(A()); } // called!
Run Code Online (Sandbox Code Playgroud)
参数传递只是复制初始化的一个上下文.另一种是使用复制初始化语法的"纯"形式
B b = A(); // called!
Run Code Online (Sandbox Code Playgroud)
在条件运算符中,如果转换为的类型是左值,则可以转换为引用类型.
struct B { };
struct A {
operator B&() { static B b; return b; }
};
int main() { B b; 0 ? b : A(); } // called!
Run Code Online (Sandbox Code Playgroud)
另一个转换为引用是指直接绑定引用
struct B { };
struct A {
operator B&() { static B b; return b; }
};
B &b = A(); // called!
Run Code Online (Sandbox Code Playgroud)
您可能具有函数指针或引用的转换函数,并且在进行调用时,可能会使用它.
typedef void (*fPtr)(int);
void foo(int a);
struct test {
operator fPtr() { return foo; }
};
int main() {
test t; t(10); // called!
}
Run Code Online (Sandbox Code Playgroud)
这个东西有时候会变得非常有用.
始终和任何地方发生的隐式转换也可以使用用户定义的转换.您可以定义一个返回布尔值的转换函数
struct test {
operator bool() { return true; }
};
int main() {
test t;
if(t) { ... }
}
Run Code Online (Sandbox Code Playgroud)
(在这种情况下,转换为bool可以通过safe-bool惯用法更安全,禁止转换为其他整数类型.)转换在内置运算符期望某种类型的任何地方触发.但是,转换可能会受到影响.
struct test {
void operator[](unsigned int) { }
operator char *() { static char c; return &c; }
};
int main() {
test t; t[0]; // ambiguous
}
// (t).operator[] (unsigned int) : member
// operator[](T *, std::ptrdiff_t) : built-in
Run Code Online (Sandbox Code Playgroud)
调用可能不明确,因为对于成员,第二个参数需要转换,而对于内置运算符,第一个需要用户定义的转换.其他两个参数分别完美匹配.在某些情况下,呼叫可能是非模糊的(ptrdiff_t需要与之不同int).
模板允许一些不错的东西,但最好对它们非常谨慎.下面使一个类型可以转换为任何指针类型(成员指针不被视为"指针类型").
struct test {
template<typename T>
operator T*() { return 0; }
};
void *pv = test();
bool *pb = test();
Run Code Online (Sandbox Code Playgroud)
转换不是魔术.仅仅因为A转换为B而B具有foo方法并不意味着a.foo()将调用B :: foo().
编译器尝试在四种情况下使用转换
除了涉及继承的转换之外,还有三种类型的转换
编译器如何决定使用何种类型的转换以及何时(特别是当有多个选择时)非常复杂,并且我在尝试将其压缩为SO的答案方面做得不好.C++标准的第12.3节讨论了隐式构造和用户定义的转换运算符.
(可能有一些我没有想到的转换情况或方法,所以如果你看到缺少的东西,请评论或编辑它们)
将参数传递给函数(包括类的重载和默认运算符)时会发生隐式转换(无论是通过转换运算符还是非显式构造函数).除此之外,还有一些对算术类型执行的隐式转换(因此添加char和long结果会增加两个long,结果很长).
隐式转换不适用于进行成员函数调用的对象:出于隐式转换的目的,"this"不是函数参数.