完全掌握C++编程中构造函数使用的超级学习教程
构造函数是一种可初始化其类的实例的成员函数。构造函数具有与类相同的名称,没有返回值。构造函数可以具有任意数量的参数,类可以具有任意数量的重载构造函数。构造函数可以具有任何可访问性(公共、受保护或私有)。如果未定义任何构造函数,则编译器会生成不采用任何参数的默认构造函数;可以通过将默认构造函数声明为已删除来重写此行为。 #include <iostream> using namespace std; class Contained1 { public: Contained1() { cout << "Contained1 constructor." << endl; } }; class Contained2 { public: Contained2() { cout << "Contained2 constructor." << endl; } }; class Contained3 { public: Contained3() { cout << "Contained3 constructor." << endl; } }; class BaseContainer { public: BaseContainer() { cout << "BaseContainer constructor." << endl; } private: Contained1 c1; Contained2 c2; }; class DerivedContainer : public BaseContainer { public: DerivedContainer() : BaseContainer() { cout << "DerivedContainer constructor." << endl; } private: Contained3 c3; }; int main() { DerivedContainer dc; int x = 3; } 这是输出: Contained1 constructor. Contained2 constructor. BaseContainer constructor. Contained3 constructor. DerivedContainer constructor. 如果构造函数引发异常,析构的顺序与构造的顺序相反: class Box { public: Box(int width,int length,int height) : m_width(width),m_length(length),m_height(height) // member init list {} int Volume() {return m_width * m_length * m_height; } private: int m_width; int m_length; int m_height; }; 创建 Box 对象: Box b(42,21,12); cout << "The volume is " << b.Volume(); 显式构造函数 Box(int size): m_width(size),m_length(size),m_height(size){} 可以初始化 Box,如下所示: Box b = 42; 或将一个 int 传递给采用 Box 的函数: class ShippingOrder { public: ShippingOrder(Box b,double postage) : m_box(b),m_postage(postage){} private: Box m_box; double m_postage; } //elsewhere... ShippingOrder so(42,10.8);
explicit Box(int size): m_width(size),m_height(size){} 构造函数是显式函数时,此行会导致编译器错误:ShippingOrder so(42,10.8);。 class Box { Box(int width,m_height(height){} }; int main(){ Box box1{}; // call compiler-generated default ctor Box box2; // call compiler-generated default ctor } 当你调用默认构造函数并尝试使用括号时,系统将发出警告: class myclass{}; int main(){ myclass mc(); // warning C4930: prototyped function not called (was a variable definition intended?) } 这是“最棘手的解析”问题的示例。这种示例表达式既可以解释为函数的声明,也可以解释为对默认构造函数的调用,而且 C++ 分析器更偏向于声明,因此表达式会被视为函数声明。 class Box { Box(int width,m_height(height){} }; private: int m_width; int m_length; int m_height; }; int main(){ Box box1(1,2,3); Box box2{ 2,3,4 }; Box box4; // compiler error C2512: no appropriate default constructor available } 如果类没有默认构造函数,将无法通过单独使用方括号语法来构造该类的对象数组。例如,在前面提到的代码块中,框的数组无法进行如下声明: Box boxes[3]; // compiler error C2512: no appropriate default constructor available 但是,你可以使用初始值设定项列表将框的数组初始化: Box boxes[3]{ { 1,3 },{ 4,5,6 },{ 7,8,9 } }; 复制和移动构造函数 显式默认构造函数和已删除构造函数 class Box { public: Box(int width,int height){ m_width = width; m_length = length; m_height = height; } private: int m_width; int m_length; int m_height; }; class StorageBox : public Box { public: StorageBox(int width,int height,const string label&) : Box(width,length,height){ m_label = label; } private: string m_label; }; int main(){ const string aLabel = "aLabel"; StorageBox sb(1,aLabel); } 具有多重继承的类的构造函数 #include <iostream> using namespace std; class BaseClass1 { public: BaseClass1() { cout << "BaseClass1 constructor." << endl; } }; class BaseClass2 { public: BaseClass2() { cout << "BaseClass2 constructor." << endl; } }; class BaseClass3{ public: BaseClass3() { cout << "BaseClass3 constructor." << endl; } }; class DerivedClass : public BaseClass1,public BaseClass2,public BaseClass3 { public: DerivedClass() { cout << "DerivedClass constructor." << endl; } }; int main() { DerivedClass dc; } 你应看到以下输出: BaseClass1 constructor. BaseClass2 constructor. BaseClass3 constructor. DerivedClass constructor. 构造函数中的虚函数 #include <iostream> using namespace std; class BaseClass{ public: BaseClass(){ print_it(); } virtual void print_it() { cout << "BaseClass print_it" << endl; } }; class DerivedClass : public BaseClass { public: DerivedClass() { print_it(); } virtual void print_it(){ cout << "Derived Class print_it" << endl; } }; int main() { DerivedClass dc; } 这是输出: BaseClass print_it Derived Class print_it 构造函数和复合类 class Label { public: Label(const string& name,const string& address) { m_name = name; m_address = address; } string m_name; string m_address; }; class StorageBox : public Box { public: StorageBox(int width,Label label) : Box(width,height),m_label(label){} private: Label m_label; }; int main(){ // passing a named Label Label label1{ "some_name","some_address" }; StorageBox sb1(1,label1); // passing a temporary label StorageBox sb2(3,4,Label{ "another name","another address" }); // passing a temporary label as an initializer list StorageBox sb3(1,{"myname","myaddress"}); } 委托构造函数 #include <iostream> using namespace std; class ConstructorDestructor { public: ConstructorDestructor() { cout << "ConstructorDestructor default constructor." << endl; } ConstructorDestructor(int int1) { cout << "ConstructorDestructor constructor with 1 int." << endl; } ConstructorDestructor(int int1,int int2) : ConstructorDestructor(int1) { cout << "ConstructorDestructor constructor with 2 ints." << endl; throw exception(); } ConstructorDestructor(int int1,int int2,int int3) : ConstructorDestructor(int1,int2) { cout << "ConstructorDestructor constructor with 3 ints." << endl; } ~ConstructorDestructor() { cout << "ConstructorDestructor destructor." << endl; } }; int main() { ConstructorDestructor dc(1,3); } 这是输出: ConstructorDestructor constructor with 1 int. ConstructorDestructor constructor with 2 ints. ConstructorDestructor constructor with 3 ints. 所有构造函数完成后,完全初始化的构造函数将立即创建对象。 DerivedContainer(int int1) 成功,但是 DerivedContainer(int int1,int int2) 失败,并调用析构函数。 class ConstructorDestructor { public: ConstructorDestructor() { cout << "ConstructorDestructor default constructor." << endl; } ConstructorDestructor(int int1) { cout << "ConstructorDestructor constructor with 1 int." << endl; } ConstructorDestructor(int int1,int int2) : ConstructorDestructor(int1) { cout << "ConstructorDestructor constructor with 2 ints." << endl; throw exception(); } ConstructorDestructor(int int1,int2) { cout << "ConstructorDestructor constructor with 3 ints." << endl; } ~ConstructorDestructor() { cout << "ConstructorDestructor destructor." << endl; } }; int main() { try { ConstructorDestructor cd{ 1,3 }; } catch (const exception& ex){ } } 输出: ConstructorDestructor constructor with 1 int. ConstructorDestructor constructor with 2 ints. ConstructorDestructor destructor. 继承构造函数 (C++11) #include <iostream> using namespace std; class Base { public: Base() { cout << "Base()" << endl; } Base(const Base& other) { cout << "Base(Base&)" << endl; } explicit Base(int i) : num(i) { cout << "Base(int)" << endl; } explicit Base(char c) : letter(c) { cout << "Base(char)" << endl; } private: int num; char letter; }; class Derived : Base { public: // Inherit all constructors from Base using Base::Base; private: // Can't initialize newMember from Base constructors. int newMember{ 0 }; }; int main(int argc,char argv[]) { cout << "Derived d1(5) calls: "; Derived d1(5); cout << "Derived d1('c') calls: "; Derived d2('c'); cout << "Derived d3 = d2 calls: " ; Derived d3 = d2; cout << "Derived d4 calls: "; Derived d4; // Keep console open in debug mode: cout << endl << "Press Enter to exit."; char in[1]; cin.getline(in,1); return 0; } 输出:
Derived d1(5) calls: Base(int) Derived d1('c') calls: Base(char) Derived d3 = d2 calls: Base(Base&) Derived d4 calls: Base() Press Enter to exit. using 语句可将来自基类的所有构造函数引入范围(除了签名与派生类中的构造函数相同的构造函数)。一般而言,当派生类未声明新数据成员或构造函数时,最好使用继承构造函数。 template< typename T > class Derived : T { using T::T; // declare the constructors from T // ... }; 如果基类的构造函数具有相同签名,则派生类无法从多个基类继承。 argument-declaration-list 可能为空。 默认构造函数和复制构造函数 默认构造函数可在没有参数的情况下调用。但是,如果所有参数都有默认值,则可以用参数列表声明默认构造函数。同样,复制构造函数必须接受对相同类类型的引用的单一参数。可以提供多个参数,前提是所有后续参数都有默认值。 DrawLine( Point( 13,22 ),Point( 87,91 ) ); 创建类型 Point 的两个对象,将其传递给函数 DrawLine,并在表达式(函数调用)的末尾将其销毁。 Point pt = Point( 7,11 ); 使用接受类型为 Point 的两个参数的构造函数来创建和初始化类型为 int 的对象。 // specl_calling_virtual_functions.cpp // compile with: /EHsc #include <iostream> using namespace std; class Base { public: Base(); // Default constructor. virtual void f(); // Virtual member function. }; Base::Base() { cout << "Constructing Base sub-objectn"; f(); // Call virtual member function } // from inside constructor. void Base::f() { cout << "Called Base::f()n"; } class Derived : public Base { public: Derived(); // Default constructor. void f(); // Implementation of virtual }; // function f for this class. Derived::Derived() { cout << "Constructing Derived objectn"; } void Derived::f() { cout << "Called Derived::f()n"; } int main() { Derived d; } 在运行前面的程序时,声明 Derived d 将产生以下事件序列: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |