题
我知道,如果您将某个成员保留在无参数构造函数的初始化列表之外,则将调用该成员的默认构造函数。
复制构造函数是否同样调用成员的复制构造函数,还是也调用默认构造函数?
class myClass {
private:
someClass a;
someOtherClass b;
public:
myClass() : a(DEFAULT_A) {} //implied is b()
myClass(const myClass& mc) : a(mc.a) {} //implied is b(mc.b)??? or is it b()?
}
解决方案
显式定义复制构造不调用复制构造为成员。
当输入一个构造的主体,该类别的每一个成员将被初始化。也就是说,一旦你到{
你保证你所有的成员都被初始化。
除非另有规定,成员是默认初始化它们出现在类的顺序。(如果他们不能,是形成不良的程序。)所以,如果你定义自己拷贝构造函数,它现在最多可以根据需要调用任何成员的拷贝构造函数。
下面是一个小程序,你可以某处复制粘贴和更动:
#include <iostream>
class Foo {
public:
Foo() {
std::cout << "In Foo::Foo()" << std::endl;
}
Foo(const Foo& rhs) {
std::cout << "In Foo::Foo(const Foo&)" << std::endl;
}
};
class Bar {
public:
Bar() {
std::cout << "In Bar::Bar()" << std::endl;
}
Bar(const Bar& rhs) {
std::cout << "In Bar::Bar(const Bar&)" << std::endl;
}
};
class Baz {
public:
Foo foo;
Bar bar;
Baz() {
std::cout << "In Baz::Baz()" << std::endl;
}
Baz(const Baz& rhs) {
std::cout << "In Baz::Baz(const Baz&)" << std::endl;
}
};
int main() {
Baz baz1;
std::cout << "Copying..." << std::endl;
Baz baz2(baz1);
}
AS-是,此打印:
In Foo::Foo() In Bar::Bar() In Baz::Baz() Copying... In Foo::Foo() In Bar::Bar() In Baz::Baz(const Baz&)
请注意,它的缺省初始化Baz
的成员。
通过注释出明确的拷贝构造,如:
/*
Baz(const Baz& rhs) {
std::cout << "In Baz::Baz(const Baz&)" << std::endl;
}
*/
,输出将变成这样:
In Foo::Foo() In Bar::Bar() In Baz::Baz() Copying... In Foo::Foo(const Foo&) In Bar::Bar(const Bar&)
它调用拷贝构造上两者。
如果我们再介绍Baz
的拷贝构造函数和明确复制单个成员:
Baz(const Baz& rhs) :
foo(rhs.foo)
{
std::cout << "In Baz::Baz(const Baz&)" << std::endl;
}
我们得到:
In Foo::Foo() In Bar::Bar() In Baz::Baz() Copying... In Foo::Foo(const Foo&) In Bar::Bar() In Baz::Baz(const Baz&)
正如你所看到的,一旦你明确声明拷贝构造函数的您的是负责所有类成员的复制;这是你的构造了。
这适用于所有的构造,包括移动的构造。
其他提示
是。构建函数是构建函数。
有关具有如果尚未明确添加任何其他构造函数调用该成员变量放到初始化列表默认构造函数被调用默认构造函数的任何成员变量。
详情请参阅: C++中有隐式默认构造函数吗?
短的:
- 编译器生成的“默认构造函数”:使用每个成员的默认构造函数。
- 编译器生成的“复制构造函数”:使用每个成员的复制构造函数。
- 编译器生成的“赋值运算符”:使用每个成员的赋值运算符。
有什么魔力拷贝构造函数,除此之外,如果需要的话,编译器将添加它。但在如何实际运行,没有什么特别的 - 如果你不明确地说“使用某某构造函数”,它会使用默认
不在VC9。不知道其他人。
// compiled as: cl /EHsc contest.cpp
//
// Output was:
// Child1()
// -----
// Child1()
// Child2()
// Parent()
// -----
// Child1(Child1&)
// Child2()
// Parent(Parent&)
#include <cstdio>
class Child1 {
int x;
public:
static Child1 DEFAULT;
Child1(){
x = 0;
printf("Child1()\n");
}
Child1(Child1 &other){
x = other.x;
printf("Child1(Child1&)\n");
}
};
Child1 Child1::DEFAULT;
class Child2 {
int x;
public:
Child2(){
x = 0;
printf("Child2()\n");
}
Child2(Child2 &other){
x = other.x;
printf("Child2(Child2&)\n");
}
};
class Parent {
int x;
Child1 c1;
Child2 c2;
public:
Parent(){
printf("Parent()\n");
}
Parent(Parent &other) : c1(Child1::DEFAULT) {
printf("Parent(Parent&)\n");
}
};
int main(){
printf("-----\n");
Parent p1;
printf("-----\n");
Parent p2(p1);
return 0;
}
根据不同的碱基调用构造函数是如何发起的,该成员的构造函数将被调用相同的方式。例如,让我们开始:
struct ABC{
int a;
ABC() : a(0) { printf("Default Constructor Called %d\n", a); };
ABC(ABC & other )
{
a=other.a;
printf("Copy constructor Called %d \n" , a ) ;
};
};
struct ABCDaddy{
ABC abcchild;
};
您可以做以下测试:
printf("\n\nTest two, where ABC is a member of another structure\n" );
ABCDaddy aD;
aD.abcchild.a=2;
printf( "\n Test: ABCDaddy bD=aD; \n" );
ABCDaddy bD=aD; // Does call the copy constructor of the members of the structure ABCDaddy ( ie. the copy constructor of ABC is called)
printf( "\n Test: ABCDaddy cD(aD); \n" );
ABCDaddy cD(aD); // Does call the copy constructor of the members of the structure ABCDaddy ( ie. the copy constructor of ABC is called)
printf( "\n Test: ABCDaddy eD; eD=aD; \n" );
ABCDaddy eD;
eD=aD; // Does NOT call the copy constructor of the members of the structure ABCDaddy ( ie. the copy constructor of ABC is not called)
输出:
Default Constructor Called 0
Test: ABCDaddy bD=aD;
Copy constructor Called 2
Test: ABCDaddy cD(aD);
Copy constructor Called 2
Test: ABCDaddy eD; eD=aD;
Default Constructor Called 0
享受。
在编译器提供的默认cctor,你怎么想的编译器的成员变量?它复制的构建体它。
在同样,如果cctor是用户定义的,并且如果一个遗漏了一些成员,这些成员不能留初始化。类不变量施工期间设立,必须经常保养。因此,编译器会替你。