0

我不明白这段代码是如何编译的。有人可以解释那里发生了什么。

#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;
}

optput 是:构造函数调用

PS:我想不出比这更贴切的标题了,谁能想到更好的标题,请修改。

4

7 回答 7

10

的类型"copy me"char const[8],衰减为char const *。由于默认构造函数不是explicit"copy me"因此可以隐式转换为B,因此ob可以从该隐式转换的临时对象复制构造B

如果声明了默认构造函数explicit,您将不得不编写以下内容之一:

B ob1 = B("copy me");
B ob2("copy me");

如果还声明了复制构造函数explicit,您将不得不说其中之一:

B ob3(B("copy me"));
B ob4("copy me");

在实践中,所有的副本都将被任何半体面的编译器忽略,并且您总是以一个默认的构造函数调用结束。

于 2012-09-16T12:18:23.593 回答
7

因为这

B ob = "copy me";

调用复制构造函数,它接受参数const B &b 并且你的类B有一个构造函数

B(const char* str = "\0")

未定义explicit。_

允许编译器进行一次隐式转换。


那么,这里会发生什么:

B ob = "copy me";

是:

  1. B使用提供的创建一个临时的、未命名的对象const char* str- 这是允许的,因为class B有构造函数,它接受一个参数并且未定义为explicit. 换句话说,所有具有类型的对象B都可以从一个const char*
  2. 使用在 中创建ob的临时对象创建对象1.
于 2012-09-16T12:18:42.823 回答
7

如果将关键字显式添加到默认构造函数以防止隐式转换。然后它不会编译。你的答案是隐式转换。

于 2012-09-16T12:19:22.627 回答
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;
}
于 2012-09-16T12:19:13.353 回答
3

[它不应该编译,因为] 指定的行在数据类型中不匹配

没有编译错误,因为存在一个将其作为参数的构造B函数const char*,允许在 和 之间进行const char*转换B

于 2012-09-16T12:18:38.020 回答
0

这是因为隐式转换。将一个 Explicit 添加到您的 Default 构造函数并尝试。它将无法编译。

于 2012-09-16T12:32:24.970 回答
-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,因此可以在此上下文中使用。

要么创建一个临时对象,然后复制(您会看到打印出的两行),要么省略副本,并且仅调用转换构造函数以直接在目标处构造(您只会看到打印的一行)。即使复制构造函数有副作用,该标准也明确允许这样做。

程序执行将打印构造函数调用到标准输出。它可能会也可能不会打印Copy constructor called . 没有错误。

于 2012-09-16T12:40:18.083 回答