这是我的代码:
1 #include <cstdio>
2
3 struct Foo;
4
5 struct Bar {
6 Foo *foo;
7 Bar(const Foo& fo) {
8 printf("In Bar copy_contr\n");
9 }
10
11 Bar& operator=(Foo& fo) {
12 printf("In Bar assignment\n");
13 this->foo = &fo;
14 }
15 };
16
17 struct Foo {
18 Bar *bar;
19 Foo() {
20 printf("In default\n");
21 }
22
23 Foo(const Bar& b) {
24 printf("In Foo copy constructor\n");
25 }
26
27 operator Bar() {
28 printf("In typecast from Foo to Bar\n");
29 return *(this->bar);
30 }
31
32 };
33
34
35 int f(Bar b) {
36 return 0;
37 }
38
39 int main() {
40 Foo fo;
41 f(fo);
42 Bar *b = &static_cast<Bar>(fo);
43
44 return 0;
45 }
这是打印输出:
In default
In typecast from Foo to Bar
In Bar copy_contr
我对第3次打印输出感到困惑:如何调用复制构造函数,它应该是类型转换,那里有特定的static_cast。
我也有一个有趣的发现 - 如果我注释掉第27行 - 第30行,基本上会消除类型转换功能,打印输出更改为 在默认情况下 在Bar copy_contr中 在Bar copy_contr
中所以看起来编译器有一些机制可以按某种顺序搜索一些转换函数,任何人都有标准的强制说明机制是什么?
我正在使用g ++ v4.1.2。
谢谢!
答案 0 :(得分:2)
我对第3次打印输出感到困惑:如何调用复制构造函数,它应该是类型转换,那里有特定的static_cast。
表达式 static_cast&lt; T&gt;(v)的结果是将表达式v转换为T类型的结果。
如果声明 T t(e),则可以使用 static_cast&lt; T&gt;(e)形式的static_cast将表达式e显式转换为类型T.对于一些发明的临时变量来说,这是一个良好的形式。
这种显式转换的效果与执行声明和初始化,然后使用临时变量作为转换结果相同。
由此可以清楚地说明为什么在这种情况下调用转换构造函数。
我也有一个有趣的发现 - 如果我注释掉第27行 - 第30行,基本上会消除类型转换功能,打印输出更改为默认情况下在栏中copy_contr在栏中copy_contr
您在问为什么选择转换函数 Foo :: operator Bar (如果可用)将参数fo从Foo转换为Bar而不是转换构造函数 Bar :: Bar( const Foo&amp;) ....
所以看起来编译器有一些机制可以按某种顺序搜索一些转换函数,任何人都有标准的强制说明机制是什么?
用户定义的转换仅在明确无误的情况下应用。但请注意以下特定情况:
因此选择的转换是 Foo :: operator Bar(),原因与:
class X
{
void f();
void f() const;
};
X x;
x.f();
上面选择了f的非const版本。 Foo fo是非const的,因此选择了非const版本。
如果转换函数是const或者转换构造函数采用了非const引用,那么就会出现歧义并且不会编译。
如果转换函数是const并且转换构造函数采用了非const引用,它将选择转换构造函数而不是转换函数。
答案 1 :(得分:0)
您认为“演员”和“转换”之间的区别是什么?演员要求将一个值转换为另一个值。类类型之间的转换是通过构造进行的。
也许你正试图将Foo对象重新解释为Bar?这需要不同的语法。
您在代码中使用了错误的术语。您称为“复制构造函数”的两个构造函数根本不是复制构造函数。它们是转换构造函数。它们允许从Foo
构建Bar
,反之亦然。
复制构造函数允许从类X
的现有实例构造类X
的实例。
如果您将printf
更改为“In ...转换构造函数”,则会更有意义。