1.继承中的构造函数访问顺序
由于父类和子类中都有构造函数和析构函数,那么子类对象在创建时父类先进行构造,还是子类先进行构造呢?同样在子类对象释放时,是父类先进行释放,还是子类先进行释放呢?这都有个先后顺序的问题。答案是当从父类派生一个子类并声明一个子类的对象时,它将先调用父类的构造函数,然后调用当前类的构造函数来创建对象;在释放子类对象时,先调用的是当前类的析构函数,然后是父类的析构函数。下面来个例子:
#include<iostream>
using namespace std;
class Employee
{
public:
int id;
char name[100];
char depart[100];
Employee()
{
cout << "Employee类构造函数被调用" << endl;
}
~Employee()
{
cout << "Employee类析构函数被调用" << endl;
}
};
class Operator:public Employee
{
public:
char password[100];
Operator()
{
strcpy(name,"Johnson666");
cout << "Operator类构造函数被调用" << endl;
}
~Operator()
{
cout << "Operator类析构函数被调用" << endl;
}
};
int main()
{
Operator o;
cout << o.name << endl;
return 0;
}
结果:
从图中可以看出,在定义Operator类对象时,首先调用的是父类Employee的构造函数,然后是Operator类的构造函数。子类对象的释放过程则与其构造过程恰恰相反,先调用自身的析构函数,然后再调用父类的析构函数。
最后简单总结一句话:先构造后析构,后构造先析构。
2.子类显式调用父类构造函数
当父类含有带参数的构造函数时,创建子类会调用它吗?答案是通过显式方式才可以调用。
无论创建子类对象时,调用的是哪种子类构造函数,都会自动调用父类默认构造函数。若想使用父类带参数的构造函数,则需要显式的方式:
#include<iostream>
using namespace std;
class Employee
{
public:
int id;
char Name[100];
char depart[100];
Employee(char name[])
{
strcpy(Name,name);
cout << Name << "调用了Employee类带参数的构造函数" << endl;
}
Employee()
{
strcpy(Name,"Johnson666");
cout << Name << "Employee类无参构造函数被调用" << endl;
}
~Employee()
{
cout << "Employee类析构函数被调用" << endl;
}
};
class Operator:public Employee
{
public:
char password[100];
Operator(char name[]):Employee(name) //显式调用父类带参数的构造函数
{
cout << "Operator类构造函数被调用" << endl;
}
Operator():Employee("Johnson") //显式调用父类带参数的构造函数
{
cout << "Operator类析构函数被调用" <<endl;
}
};
int main()
{
Operator o1;
Operator o2("xixixi");
return 0;
}
结果:
在父类无参构造函数中初始化成员字符串数组Name为”Johnson666“.从结果上来看,子类对象创建时没有调用父类无参构造函数,调用的是带参数的构造函数。
注意:
当父类只有带参数的构造函数时,子类必须以显式方法调用父类带参数的构造函数,否则编译会出现错误。
拓展
稍微提下:如果子类中定义了一个和父类一样的成员函数,那么一个子类对象是调用子类中的成员函数。如果你想访问父类的成员函数,需要显式使用父类名。比如:
有一个父类Employee和子类Operator
Operator o;
o.outputName(); //调用子类Operator类的outputName成员函数
o.Employee::outputName(); //调用父类Employee类的outputName成员函数
来源:freebuf.com 2021-05-20 21:00:25 by: Johnson666
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
喜欢就支持一下吧
请登录后发表评论
注册