继承:使程序代码的重用度大幅度地提高了,而C++对继承有很好的支持,
基类对象不能给子类对象赋值,因为基类中的数据不充分,不含有子类全部的信息,
但是子类对象可以给基类对象赋值。
如下图所示:
例如:
student是一类,GraduateStudent是student的子类,那么
GraduateStudent gs;
Student* p = &gs;
由于p是Student指针,指向GraduateStudent对象gs的首地址,它恰好也是其中Student对象部分的首地址。
因为研究生也是学生,所以研究生对象gs赋值给s也是合理的。它裁去了专属研究生的部分,而且将研究生对象的地址赋给学生指针p也是合理的,由于学生对象地址和研究生对象地址重合,所以,p指针若转换为研究生类型是:
GraduateStudent* pGs = reinterpret_cast<GraduateStudent*>(p);
便无需修改地址就可以操作研究生了,这种reinterpret_cast转换,纯粹是地址不变而指针类型改变,即指针操作的意义改变。但前提是学生对象与研究生对象地址重合。
1. 覆盖父类操作
如果父类中有一个操作,在子类中没有重新定义,则子类可以沿用该操作,但都是父类操作。例如下列程序中,研究生类GraduateStudent继承了Student类,对象gs在显示其本人信息时,没有办法显示相关的研究生信息。这主要是GraduateStudent类中没有重载display成员函数,为了准备使用GraduateStudent类,需要在GraduateStudent类中把父类中的display成员函数进行覆盖。
#include <iostream>
#include <string>
using namespace std;
class Advisor
{
int noOfMeeting;
};
class Student
{
string name;
int semesterHours;
double average;
public:
Student(string pName = "noName")
{
name = pName;
average = 0;
semesterHours = 0;
}
void addCourse(int hours, double grade)
{
double totalGrade = (semesterHours * average + grade);
semesterHours += hours;
average = semesterHours ? totalGrade / semesterHours : 0;
}
void display()
{
cout << "name=\"" << name << "\"" << ", hours=" << semesterHours << ", average=" << average << endl;
}
int getHours()
{
return semesterHours;
}
double getAverage()
{
return average;
}
};
class GraduateStudent : public Student
{
Advisor advisor;
int qualifierGrade;
public:
GraduateStudent(string pName = "noName"):Student(pName)
{
qualifierGrade = 0;
}
int getQualifier()
{
return qualifierGrade;
}
void display()
{
Student::display();
cout << "qualifierGrade=" << qualifierGrade << endl;
}
};
int main()
{
Student ds("Lo lee undergraduade");
GraduateStudent gs("WU fantasy");
ds.addCourse(3, 2.5);
ds.display();
gs.addCourse(3, 3.0);
gs.display();
return 0;
}
2. 同化效应
在上述代码中,GraduateStudent类继承了Student类,当以自己的身份表现时,显示了自身的特色。但是,当以研究生对象复制(传递)给学生时,研究生的个性消失了,如下代码所示:
void fun(Student& x)
{
x.display();
}
int main()
{
Student s("Lo lee undergraduate");
GraduateStudent gs("John");
fun(s);
fun(gs);
return 0;
}
代码输出如下:
name="Lo lee undergraduate", hours=0, average=0
name="John", hours=0, average=0
从输出结果可以看出,Student类对象s和GraduateStudent类对象gs作为参数传递给fun函数时,gs在fun函数中并不被看作为研究生,而被看作Student类对象进行操作。