*** 关于构造函数,默认构造函数,构造函数的默认参数
【自我总结】
1.默认构造函数不仅可以是无参的,也可以是有参的,但所有参数必须指定默认值。一个类只能有一个默认构造函数。
2.什么时候调用默认构造函数?
a.声明类的对象时没有括号时。如:classA objA;
b.子类构造函数没有显式调用父类构造函数时
3.构造函数中的默认参数要从右向左指定。
classA(int a=0, int b){}; //错误
classA(int a, int b=0){}; //正确
构造方法用来初始化类的对象,与父类的其它成员不同,它不能被子类继承(子类可以继承父类所有的成员变量和成员方法,但不继承父类的构造方法)。因此,在创建子类对象时,为了初始化从父类继承来的数据成员,系统需要调用其父类的构造方法。
如果没有显式的构造函数,编译器会给一个默认的构造函数,并且该默认的构造函数仅仅在没有显式地声明构造函数情况下创建。
构造原则如下:
1. 如果子类没有定义构造方法,则调用父类的无参数的构造方法。
2. 如果子类定义了构造方法,不论是无参数还是带参数,在创建子类的对象的时候,首先执行父类无参数的构造方法,然后执行自己的构造方法。
3. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数,则会调用父类的默认无参构造函数。
4. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数且父类自己提供了无参构造函数,则会调用父类自己的无参构造函数。
5. 在创建子类对象时候,如果子类的构造函数没有显示调用父类的构造函数且父类只定义了自己的有参构造函数,则会出错(如果父类只有有参数的构造方法,则子类必须显示调用此带参构造方法)。
6. 如果子类调用父类带参数的构造方法,需要用初始化列表的方式。
结论:子类构造函数必须要调用父类的构造函数(无论显式还是隐式),本质原因在于继承的性质决定了必须先有父再有子!
1. 默认构造函数主要是用来完成如下形式的初始化的:
testClass classA; // 或者 testClass *classA = new testClass;
在这种情况下,如果没有提供默认构造函数,编译器会报错;
非默认构造函数在调用时接受参数,如以下形式:
testClass classA(12,'H'); //或者 testClass *classA = new testClass(12,'H');
2. 如果程序猿没有定义任何构造函数,则编译器会自动定义默认构造函数,其形式如 testClass() {}; 可以看出,编译器自动提供的默认构造函数是 啥也没有啊 ;
3. 定义默认构造函数有两种方式,如上述代码展示的,一是定义一个无参的构造函数,二是定义所有参数都有默认值的构造函数 ;
4. 注意:一个类只能有一个默认构造函数!也就是说上述两种方式不能同时出现,一般选择 testClass(); 这种形式的默认构造函数 ;
5. 只要程序猿定义了构造函数,编译器就不会再提供默认构造函数了,所以,程序猿最好再手动定义一个默认构造函数,以防出现 testClass a; 这样的错误。
#include <iostream> #include <string.h> using namespace std; class A { public: A(int x):a(x){}; void printA (void) { cout << "a = " << a << endl; } private: int a; }; class B: public A { public: B(int x=0, int y=0):A(x) { b = y; } void printB(void) { cout << "b = " << b << endl; } private: int b; }; int main() { B obj(1,2); obj.printA(); obj.printB(); return 0; }