面对对象编程进阶(2)
这节是上届的延续,所以我就接着上节编号了~
6.多态与虚函数
还记得之前我们讲过的C++函数的重载吗?C++在处理同名函数有三种方法,除了重载,在面对对象编程中还特有另外两种,即隐藏和覆盖。
隐藏
如果父类和子类拥有一个相同名称的方法,那么不管参数列表是否相同,子类的实例都无法调用父类的同名方法。这便是因为父类的该方法在子类中被隐藏了。但是如果我们用父类指针指向子类实例再调用这个方法,就只能调用到父类的这个方法了。看个例子:
class Student
{
public:
void test(string a)
{
cout<<"This is Student"<<endl;
}
};
class undergraduate:public Student
{
public:
void test(char a)
{
cout<<"This is undergraduate"<<endl;
}
};
int main() // 为了展示隐藏和重载的区别,两个方法的参数列表故意设置成不同
// 其实可以完全一样
{
Student ZhangSan,*p1;
undergraduate LiSi;
ZhangSan.test("me");
LiSi.test('m');
// LiSi.test("me"); // 这里会报错,原因是父类的test方法会在派生中被隐藏,LiSi是子类的实例,无法找到被隐藏的方法
// 如果子类的test是父类的重载,这个语句执行后会打印This is Student
// 实际上,父类和子类里的同名方法可以使用类型相同的参数而不影响隐藏。
p1=&ZhangSan;
// 使用父类指针指向子类实例也只能调用父类的test方法
p1->test("me");
p1=&LiSi;
p1->test("me");
// 输出为:This is Student
// This is undergraduate
// This is Student
// This is Student
}
这里插入一个冷知识,C++中的char类型需要用单引号加字符的方式赋值,双引号加字符会被C++编译器默认为const char类型从而无法赋值给char类型变量哦。
覆盖
覆盖的实现需要声明虚函数作为基类和派生类中同名的方法。如果我们在基类中定义了一个虚函数,在派生类中用同名函数覆写了该虚函数,大家猜一猜,如果此时我们用一个基类指针指向派生类实例,再去调用虚函数,调用的会只是基类中的虚函数吗:
class Student // 这个大括号里的叫类定义
{
public:
virtual void study (); // virtual用于在基类中声明一个虚函数
};
void Student::