目录
使用派生类
要使用派生类,程序首先要能够访问基类声明,所以通常将基类声明和派生类声明放在同一个头文件中(也可以把它们放在不同的头文件中,但由于这两个类是相关的,因此通常把它们放在同一个头文件中),需要注意的是,在基类和派生类声明的头文件中,基类声明必须放在派生类声明的前面,否则编译时会报无法找到基类定义的错误。同理,基类和派生类的方法定义也通常放在一个.cpp文件中。
如《类继承》文章中的Student类和CulturalStudent类。
cpp
class Student
{
public:
Student(string name_);
Student(string name_, unsigned short yw, unsigned short sx, unsigned short yy);
~Student();
void scoreSet(int yuwen_score_, int shuxue_score_, int yingyu_score_);
unsigned short get_yuwen_score() { return yuwen_score; }
unsigned short get_shuxue_score() { return shuxue_score; }
unsigned short get_yingyu_score() { return yingyu_score; }
string get_name() { return name; }
void show_score()
{
cout << "语文分数:" << yuwen_score << endl;
cout << "数学分数:" << shuxue_score << endl;
cout << "英语分数:" << yingyu_score << endl;
}
private:
std::string name;
unsigned short yuwen_score;
unsigned short shuxue_score;
unsigned short yingyu_score;
};
class CulturalStudent:public Student
{
private:
unsigned short lishi_score;
unsigned short zhengzhi_score;
public:
CulturalStudent(string name_, unsigned short yw, unsigned short sx, unsigned short yy,
unsigned short ls, unsigned short zz);
CulturalStudent(const Student& st, unsigned short ls, unsigned short zz);
unsigned short get_lishi_score() { return lishi_score; }
unsigned short get_zhengzhi_score() { return zhengzhi_score; }
void show_name_and_score(Student& st);
};
派生类和基类之间的关系
- 对于公有派生,派生类对象可以使用基类的方法。
例如:
cpp
CulturalStudent st1("xiaoming", 82, 82, 84, 90, 91);
st1.get_shuxue_score();
- 基类指针可以在不进行显式类型转换的情况下指向派生类对象;基类引用可以在不进行显式类型转换的情况下引用派生类对象。
例如:
cpp
CulturalStudent st1("xiaoming", 82, 82, 84, 90, 91);
Student *st2 = &st1;
Student &st3 = st1;
st2->get_shuxue_score();
st3.get_shuxue_score();
通常,C++要求引用和指针类型与被赋给的类型匹配,但这一规则对继承来说是例外。不过,这种例外是单向的,不可以将基类对象和地址赋给派生类引用和指针。
基于这个规则,使用基类引用作为形参的函数可以用基类对象或派生类对象作为实参。
cpp
void CulturalStudent::show_name_and_score(Student& st)
{
cout << "name:" << st.get_name();
cout << " shuxue:" << st.get_shuxue_score();
}
上面的函数中,函数参数是基类引用,它可以指向基类对象或派生类对象,所以实参可以使用Student类对象或CulturalStudent类对象。以下调用都是可以的:
cpp
CulturalStudent st1("xiaoming", 82, 82, 84, 90, 91);
Student *st2 = &st1;
st1.show_name_and_score(*st2);
st1.show_name_and_score(st1);
同理,对于形参为指向基类的指针的函数,也存在类似的关系,可以使用基类对象的地址或派生类对象的地址作为实参。
**引用兼容性属性也能够将基类对象初始化为派生类对象。**如:
cpp
CulturalStudent st1("xiaoming", 82, 82, 84, 90, 91);
Student st5(st1);
初始化st5的过程如下:
Student st5(st1)匹配的构造函数原型为:Student(const CulturalStudent&),Student类中没有这样的构造函数,但存在隐式复制构造函数:Student(const Student&),形参是基类引用,因此可以引用派生类对象。将t5初始化为t1时,将复制t1对象中的name,yuwen_score,shuxue_score, yingyu_score成员值。具体的说,t5被初始化为嵌套在t1对象中的Student对象。
同样,也可以将派生类对象赋给基类对象,如下:
cpp
CulturalStudent st1("xiaoming", 82, 82, 84, 90, 91);
Student st5("xiaohong", 90, 89, 78);
st5 = st1;
此时,程序将调用基类的隐式重载赋值操作符函数:
cpp
Student& operator=(const Student&)const;
重载赋值操作符函数的形参是基类引用,因此,可以将派生类对象作为实参赋给它。