我们都知道C++有三大特性,封装、继承、多态。今天讲一下多态。首先我们先了解一下父子类之间的同名覆盖问题。
父子类之间的同名覆盖问题
先看一段代码:
#include "stdio.h"
class Parent
{
public:
Parent()
{
mi = 100;
}
int mi;
};
class Child :Parent
{
public:
Child()
{
mi = 200;
}
int mi;
};
int main(int argc , char *argv[])
{
Child c;
printf("mi: %d \n",c.mi);
}
我在父类Parent中定义了mi变量,在子类Child中也同样定义了mi变量,这时,子类对象Child c;按照我们的预期应该会打印子类中的mi变量值,看看输出:
确实如我们所想,打印了子类的mi值。Child c是继承自Parent的,Parent中也是有mi变量的,那父类中的mi变量是就此被覆盖了吗?当然不是!父类中的变量是被“隐藏”了,但确真实存在,如果子类对象要调用父类中的同名变量,采用这种方式:c.Parent::mi
。
这里是同名的变量,我们是否能够延伸到同名的函数也能得到这个结论呢?看一段代码:
#include "stdio.h"
class Parent
{
public:
Parent()
{
mi = 100;
}
void print()
{
printf("I'm Parent \n");
}
void print(int a)
{
printf("I'm Parent a: %d \n",a);
}
void print(int a , int b)
{
printf("I'm Parent a: %d ,b : %d \n",a,b);
}
int mi;
};
class Child : public Parent
{
public:
Child()
{
mi = 200;
}
void print(int a)
{
printf("I'm Child a: %d \n",a);
}
void print(int a , int b,int c )
{
printf("I'm Child a: %d ,b : %d ,c : %d \n",a,b,c);
}
int mi;
};
int main(int argc , char *argv[])
{
Child c;
//c.print();//print()是定义在Parent类中的函数,Child子类对象的作用域中并不包含这两个函数。
c.print(11,12,23);
c.print(1);重写父类中的print(a)
c.Parent::print(1);//父类中的print(a)并不是被替换,而是隐藏起来,通过::作用域标识符可以调用
return 0;
}
输出如图所示:
我们可以得出这样的结论:
- 函数重写 与 函数重载有很大不同,重写 指的是子类重新实现父类中的同名函数,子类对象直接调用的是子类中的函数,父类中的同名函数被隐藏了。需要t通过 :: 作用域标识符调用。重载 指的是同一个作用域中,同名函数通过函数参数列表分辨彼此,虽然函数名相同,但是本质上就是完全不同的函数,函数重载必须发生在同一个作用域中。父类和子类之间是属于两个不同的作用域。
原创内容,禁止转载
王雄 首次更新于2021.03.08