C++构造函数和初始化器行为。这5个代码有什么区别?

问题描述:

我是新来的c + +编程语言。我编写了几种代码模式来理解C++构造函数和初始化函数。但我找不到为什么一个构建失败,另一个没有。在我看来,似乎没有这样的区别,一个失败,另一个不失败。代码是以下5个代码。代码示例1-2,2-3,3-4,4-5之间有什么区别。为什么一个失败,但另一个不失败?C++构造函数和初始化器行为。这5个代码有什么区别?

Additional Info: 我要建这些代码和Xcode 8.2。


守则

实施例1:

class A{ 
public: 
    A(int xxx) { } 
}; 

int main(){ 
    A a; // Fail here. I see this is because there is no default constructor in definition of class A. 
} 

实施例2:

class A{ 
public: 
    A(int xxx) { } 
}; 

class B{ 
public: 
    A a; // No fail. Why? I supposed it will fail like Example 1. 
}; 

int main(){ 

} 

实施例3:

class A{ 
public: 
    A(int xxx) { } 
}; 

class B{ 
public: 
    A a;   // No fail here. 
    B(int xxx) { } // But fail here. Why? I just added constructor to Example 2. 
}; 

int main(){ 

} 

实施例4:

class A{ 
public: 
    A(int xxx) { } 
}; 

class B{ 
public: 
    A a; 
    B(int xxx) : a(123) { } // No fail. Why Just adding ":a(123)" works. 
}; 

int main(){ 

} 

实施例5:

class A{ 
public: 
    A(int xxx) { } 
}; 

class B{ 
public: 
    A a; 
    B(int xxx){ a = 123; } // Fail again. Why? I think ":a(123)" and "a=123" is same meaning. 
}; 

int main(){ 

} 

有例如2没有错误,因为你不尝试构建B。如果添加到主B b;那么你会得到这样的错误

error: use of deleted function 'B::B()'

的原因您尝试实例化一个B是因为A a;只是一个成员声明之前,你没有得到一个错误。直到构造函数被调用并且你试图实例化a,你发现它不是默认可构造的。

例3基本上是一样的东西。既然您正在定义一个构造函数,编译器会自动添加a的默认初始值,因为您没有在成员初始值设定项列表中提供一个。当它看到A不是默认可构造的,因此它发出错误。因为你指定了如何构建a

例4不会失败。既然你这样做了,编译器不会尝试默认构造它,而是用你提供的值构造a

例5再次失败,因为例3同样的原因,试图将默认初始化添加到成员初始化列表,但不能因为它不存在,这给你的错误。

+0

我觉得这是非常细节和一个什么样的精确描述发生在这些例子中。谢谢。 –

+0

@KeiMinagawa没问题。乐意效劳。 – NathanOliver

你似乎已经掌握了大部分这一切,所以让我通读一切并澄清。

示例1:您正在尝试创建A实例而未提供所需的构造函数参数。

示例2:类B无法实例化,因为它需要创建A的实例,并且您尚未指定将哪些参数发送给其构造函数。如果您要在某处创建B的实例,那么您会在此处收到编译器错误。例如在main()中放入B b;

示例3:构造函数B::B(int)无法编译,因为您尚未为构造函数B::a(其实例A)指定有效参数。你在这里得到错误,因为在这个构造函数中,你必须指定一个```的参数。

例4:在这里,您要在初始化列表B::B中指定哪些参数应该传递给B::a。这是你需要做的,以便它进行编译。

示例5:此处您试图指定值为123。这是在构造函数B::B的主体中完成的,它在B的所有成员都被初始化后调用。它没有指定参数为a的构造函数。它只是试图在它已经被构建之后为它分配一个新的值。既然你不指定应发送到的a构造函数的值,你得到同样的错误与例3

+0

这帮了很多。我多次阅读你的答案和@ NathanOliver。最后我得到了它。谢谢。 –

  • 1比2:例2不失败,因为你永远不实例BØ A在主
  • 2比3:3例失败,因为在你的B构造你不打电话给A::A()A没有默认构造函数
  • 3比4:例4,因为你打电话不失败A::A()在您的B构造函数中。
  • 4 vs 5:示例5失败,因为(再次)您不调用A::A()A没有默认构造函数。但是123可以asigned到A(因为隐式声明的拷贝赋值运算符声明,和你有一个构造函数建立从intA
+0

很简单,我喜欢这个。当我困惑时,我一次又一次地回答这个问题。谢谢。 –

+0

我忘了说,我想你最后提到的'a = 123'可以在没有演员的情况下创建A的实例。 –

+0

@KeiMinagawa你是完全正确的,在这种情况下是可以的,因为声明了隐式声明的复制赋值操作符,并且你有一个构造函数来从'int'构建'A'。编辑我的答案。 – Rama