我不明白这段代码是如何编译的。有人可以解释一下那里发生了什么。
#include <iostream>
using namespace std;
class B
{
public:
B(const char* str = "\0") //default constructor
{
cout << "Constructor called" << endl;
}
B(const B &b) //copy constructor
{
cout << "Copy constructor called" << endl;
}
};
int main()
{
B ob = "copy me"; //why no compilation error.
return 0;
}
输入是: 构造函数叫
P.S。:我想不出一个比这更贴切的标题,任何能想到更好标题的人,请修改它。
答案 0 :(得分:10)
"copy me"
的类型为char const[8]
,其衰减为char const *
。由于默认构造函数不是explicit
,因此"copy me"
可以隐式转换为B
,因此可以从隐式转换的临时ob
复制构造B
} -object。
如果默认构造函数已声明为explicit
,则必须编写以下内容之一:
B ob1 = B("copy me");
B ob2("copy me");
如果复制构造函数也被声明为explicit
,那么你不得不说其中一个:
B ob3(B("copy me"));
B ob4("copy me");
在实践中,所有副本都将被任何半合半的编译器省略,并且您总是以一个默认的构造函数调用结束。
答案 1 :(得分:7)
因为这个
B ob = "copy me";
调用复制构造函数,它接受参数const B &b
和你的类B
有一个构造函数
B(const char* str = "\0")
不定义为explicit
。
允许编译器进行一次隐式转换。
那么,这里会发生什么:
B ob = "copy me";
是:
B
创建临时的,未命名的对象const char* str
- 这是允许的,因为class B
具有构造函数,该构造函数接受一个参数并且未定义为{{1} }。换句话说,所有类型为explicit
的对象都可以从B
const char*
。ob
醇>
答案 2 :(得分:7)
如果您将关键字显式添加到默认构造函数中以防止隐式转换。然后它将无法编译。你的答案是隐式转换。
答案 3 :(得分:4)
这是因为将赋值语句隐式转换为
B ob("copy me");
尝试此操作以使编译失败(查看explicit
关键字):
#include <iostream>
using namespace std;
class B
{
public:
explicit B(const char* str = "\0") //default constructor
{
cout << "Constructor called" << endl;
}
B(const B &b) //copy constructor
{
cout << "Copy constructor called" << endl;
}
};
int main()
{
B ob = "copy me"; //why no compilation error.
return 0;
}
答案 4 :(得分:3)
[它不应该编译,因为]指定的行在数据类型中不匹配
没有编译错误,因为存在B
的构造函数,它将const char*
作为参数,允许在const char*
和B
之间进行转换。
答案 5 :(得分:0)
这是因为隐式转换。将一个Explicit添加到您的默认构造函数并尝试。它将无法编译。
答案 6 :(得分:-1)
编辑:在与Kerrek SB讨论后,我得到了C ++ 11标准的副本。我错了,这是暂时的。我正在编辑此回复以反映我新获得的理解。
15年前,我非常了解C ++(大约是第一个标准发布的时候)。我从1998年末开始没有使用它,所以我已经忘记了很多,而且我对最近的标准几乎一无所知。代码是正确的。
B ob = "copy me"; //why no compilation error.
没有错误。这被解析为初始化变量的声明。 B
是类型,ob
变量的名称,"copy me"
初始化程序。
初始化程序的类型为const char*
,在类B中,有一个构造函数,它接受一个const char*
类型的单个参数。该构造函数未被explicit
声明限制,因此可以在此上下文中使用。
创建临时对象然后复制(您看到两行都打印出来)或者删除了副本,只调用转换构造函数直接在目标构造(您只看到一行打印)。即使拷贝构造函数有副作用,标准也明确允许这样做。
程序执行会将名为的构造函数打印到stdout。它可能会也可能不会打印复制构造函数。没有错误。