又是类的 "构造函数", "拷贝构造函数" 和 "赋值操作符"

// -------------------------------------------------------------------[代码]---- #include "iostream" // 这里不使用"尖括号"是因为 HTML 会认为它是 tag. class Foo { public: Foo() { std::cout << "Foo's default-constructor is running." << std::endl; } Foo(const Foo& foo) { std::cout << "Foo's copy-constructor is running." << std::endl; this->_c = foo._c; // 这里不写成 *this = foo; , 是不想在 Foo 的拷贝构造 // 函数中调用它的赋值操作符 (因为赋值操作符中有打印信 // 息, 无益于对程序输出的理解.). } Foo& operator=(const Foo& foo) { std::cout << "Foo's assign-operator is running." << std::endl; if (this != &foo) { this->_c = foo._c; } return *this; } private: char _c; }; // Foo class Foo2 { public: Foo2() { std::cout << "Foo2's default-constructor is running." << std::endl; } Foo2(const Foo2& foo2) { std::cout << "Foo2's copy-constructor is running." << std::endl; this->_c = foo2._c; // 这里不写成 *this = foo2; , 是不想在 Foo2 的拷贝构 // 造函数中调用它的赋值操作符 (因为赋值操作符中有打 // 印信息, 无益于对程序输出的理解.). } Foo2& operator=(const Foo2& foo2) { std::cout << "Foo2's assign-operator is running." << std::endl; if (this != &foo2) { this->_c = foo2._c; } return *this; } private: char _c; }; // Foo2 class Foo3 { public: Foo3() { std::cout << "Foo3's default-constructor is running." << std::endl; } Foo3(const Foo3& foo3) { std::cout << "Foo3's copy-constructor is running." << std::endl; this->_c = foo3._c; // 这里不写成 *this = foo3; , 是不想在 Foo3 的拷贝构 // 造函数中调用它的赋值操作符 (因为赋值操作符中有打 // 印信息, 无益于对程序输出的理解.). } Foo3& operator=(const Foo3& foo3) { std::cout << "Foo3's assign-operator is running." << std::endl; if (this != &foo3) { this->_c = foo3._c; } return *this; } private: char _c; }; // Foo3 class Bar { public: // 这里的 __thiscall 调用约定关键字可以省略, 因为 __thiscall 是 C++ 类成员 // 函数的默认调用约定. 写出来, 是想说明参数的入栈顺序是从右向左. // // 注: 在 VC++2005 以前 (不含 VC++2005) 的 VC++ 版本中, __thiscall 不是关键 // 字, 程序员不能显式使用该关键字 (VC++2005 中可以). __thiscall Bar(Foo foo, Foo2 foo2) { std::cout << "Bar's constructor is running." << std::endl; _foo = foo; _foo2 = foo2; } private: Foo _foo; Foo2 _foo2; }; // Bar class Baz { public: // 这里的 __thiscall 调用约定关键字可以省略, 因为 __thiscall 是 C++ 类成员 // 函数的默认调用约定. 写出来, 是想说明参数的入栈顺序是从右向左. // // 注: // 1. 在 VC++2005 以前 (不含 VC++2005) 的 VC++ 版本中, __thiscall 不是关键 // 字, 程序员不能显式使用该关键字 (VC++2005 中可以). // 2. 构造函数初始化列表中写成 _foo3(foo3), _foo(foo), 而不 // 是 _foo(foo), _foo3(foo3) 是想强调: 类数据成员的初始化 // 次序由它们在类中的定义次序决定, 而非构造函数初始化列表 // 中的次序决定. __thiscall Baz(Foo& foo, Foo2 foo2, Foo3 foo3): _foo3(foo3), _foo(foo) { std::cout << "Baz's constructor is running." << std::endl; _foo2 = foo2; } private: Foo _foo; Foo2 _foo2; Foo3 _foo3; }; // Baz class Foobar { public: // 这里的 __thiscall 调用约定关键字可以省略, 因为 __thiscall 是 C++ 类成员 // 函数的默认调用约定. 写出来, 是想说明参数的入栈顺序是从右向左. // // 注: 在 VC++2005 以前 (不含 VC++2005) 的 VC++ 版本中, __thiscall 不是关键 // 字, 程序员不能显式使用该关键字 (VC++2005 中可以). __thiscall Foobar(Foo foo, Foo2& foo2, Foo3 foo3): _foo(foo), _foo2(foo2) { std::cout << "Foobar's constructor is running." << std::endl; foo3; // 避免: warning C4100: 'foo3' : unreferenced formal parameter } private: Foo _foo; Foo2 _foo2; }; // Foobar int main() { Foo foo; Foo2 foo2; Foo3 foo3; std::cout << "----------------[1]----------------" << std::endl; Bar bar(foo, foo2); std::cout << "----------------[2]----------------" << std::endl; Baz baz(foo, foo2, foo3); std::cout << "----------------[3]----------------" << std::endl; Foobar foobar(foo, foo2, foo3); std::cout << "----------------[4]----------------" << std::endl; return 0; } // main // -------------------------------------------------------------------[代码]---- 

/* ----------------------------------------------------------------------[输出]---- Foo's default-constructor is running. // main 函数中局部对象 foo 定义时产生的. Foo2's default-constructor is running. // main 函数中局部对象 foo2 定义时产生的. Foo3's default-constructor is running. // main 函数中局部对象 foo3 定义时产生的. ----------------[1]---------------- Foo2's copy-constructor is running. // Bar 构造函数的第 2 个参数 foo2 创建时产生的. Foo's copy-constructor is running. // Bar 构造函数的第 1 个参数 foo 创建时产生的. Foo's default-constructor is running. // Bar 类的数据成员 _foo 初始化时产生的. Foo2's default-constructor is running. // Bar 类的数据成员 _foo2 初始化时产生的. Bar's constructor is running. // Bar 构造函数函数体开始执行时产生的. Foo's assign-operator is running. // Bar 构造函数函数体内 _foo = foo; 执行时产生的. Foo2's assign-operator is running. // Bar 构造函数函数体内 _foo2 = foo2; 执行时产生的. ----------------[2]---------------- Foo3's copy-constructor is running. // Baz 构造函数的第 3 个参数 foo3 创建时产生的. Foo2's copy-constructor is running. // Baz 构造函数的第 2 个参数 foo2 创建时产生的. Foo's copy-constructor is running. // Baz 构造函数初始化列表初始化 Baz 类的数据成员 _foo 时产生的. Foo2's default-constructor is running. // Baz 类的数据成员 _foo2 初始化时产生的. Foo3's copy-constructor is running. // Baz 构造函数初始化列表初始化 Baz 类的数据成员 _foo3 时产生的. Baz's constructor is running. // Baz 构造函数函数体开始执行时产生的. Foo2's assign-operator is running. // Baz 构造函数函数体内 _foo2 = foo2; 执行时产生的. ----------------[3]---------------- Foo3's copy-constructor is running. // Foobar 构造函数的第 3 个参数 foo3 创建时产生的. Foo's copy-constructor is running. // Foobar 构造函数的第 1 个参数 foo 创建时产生的. Foo's copy-constructor is running. // Foobar 构造函数初始化列表初始化 Foobar 类的数据成员 _foo 时产生的. Foo2's copy-constructor is running. // Foobar 构造函数初始化列表初始化 Foobar 类的数据成员 _foo2 时产生的. Foobar's constructor is running. // Foobar 构造函数函数体开始执行时产生的. ----------------[4]---------------- ----------------------------------------------------------------------[输出]---- */ 

/* ----------------------------------------------------------------------[结论]---- 默认调用约定 (__thiscall) 下,类的构造函数,数据成员,以及相关 XXXX 中,各 YYYY 执行的先后次序: 1) 先按从右向左的顺序执行各参数的拷贝构造函数(当然,指类类型参数,并且不是指针或 引用类型!),无论类中是否有该参数类类型的数据成员; 2) 如果构造函数有初始化列表,则按类的各类类型数据成员在类中定义的次序,通过构造函 数初始化列表,使用各类类型数据成员的拷贝构造函数,对其进行初始化(说明:如果构 造函数初始化列表中如果跳过了某(几)个类类型数据成员,那么,前述的,通过构造函 数初始化列表,初始化类类型数据成员的过程中,就会——依然按数据成员在类中定义的次 序——混合着执行跳过的那(几)个的默认构造函数(不会再执行它(们)的拷贝构造函数; 另,如果有那个没有构造函数,程序出错); 3) 如果没有构造函数初始化列表,则按各类类型数据成员在类中定义的次序分别执行其默认 构造函数; 4) 执行构造函数函数体的内容。 ----------------------------------------------------------------------[结论]---- */ 

你可能感兴趣的:(html,c,Class,iostream,Constructor)