一、继承
1、 定义和作用
C++继承机制是利用已有的数据类型来定义新的数据类型,用来派生新类的类称为基类或父类,由已存在的类派生出的新类称为派生类或子类。派生类不仅拥有新定义的成员,同时拥有基类的成员。
一个派生类可以从一个基类或多个基类派生,前者称为单继承,后者称为多继承。
1)单继承的定义格式如下:
class<派生类名>:<继承方式><基类名>
{
<派生类新定义成员>
};
2)多继承的定义格式如下:
class<派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
<派生类新定义成员>
};
继承可以扩展已存在的代码,目的是代码复用。
2、 继承方式
公有继承(public)、私有继承(private)、保护继承(protected)是常用的三种继承方式。
1)公有继承(public)
公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的,不能被这个派生类的子类所访问。
2)私有继承(private)
私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。
3)保护继承(protected)
保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的。
在不同的继承方式下,派生类对基类的成员访问权限如下表所示:
继承方式\成员类型 |
public |
protected |
private |
public |
public |
protected |
不可见 |
protected |
protected |
protected |
不可见 |
private |
private |
private |
不可见 |
如果继承方式,class默认采用私有继承,而struct默认的是public继承。
二、多态
1、 定义和作用
C++多态性可以简单地概括为“一个接口,多种方法”。父类对象可以根据当前子类对象赋值的特性在运行时决定调用的函数,允许子类类型的指针赋值给父类类型的指针。多态是面向对象编程领域的核心概念。
多态的目的为了接口重用,无论传递过来的对象属于哪个类,函数都可以通过同一个接口调用到适应不同对象的实现方法。
2、 实现方式
C++中有两种实现多态的方式,分别是重载和覆盖。
1) 重载
重载是允许有多个同名的函数,但这些函数的参数列表不同,如参数个数不同和参数类型不同等。这些同名函数的调用在编译过程就确定了调用地址,编译器会根据这些函数的不同参数列表,将同名函数的名称做修饰,从而生成一些不同名称的预处理函数,属于静态绑定(早绑定)。
例如,有两个同名函数: void func(int num)和void func(string name),那么编译器做过修饰后的函数名称可能是int_func和str_func。
实际,重载只是一种语言特性,与多态无关,与面向对象也无关。
2) 覆盖
覆盖是指子类对父类的虚函数重定义。虚函数是在一般函数前面加上virtual。通过声明父类的指针,利用该指针指向一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而实现不同的方法。对虚函数的调用在编译过程中不能确定,在运行时才能确定,属于动态绑定(晚绑定)。
3、 纯虚函数
纯虚函数是在父类中声明的未定义的虚函数,函数原型后加上“=0”,如virtual void func()=0。编译器要求在任何子类中都需要重定义纯虚函数,以实现多态性。
含有纯虚函数的类称为抽象类,不能定义抽象类的对象。
3、 示例
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
class Father
{
public:
Father(){}
~Father(){}
void func()
{
cout << "1" << endl;
}
virtual void function()
{
cout << "2" << endl;
}
};
class Child : public Father
{
public:
Child(){}
~Child(){}
void func()
{
cout << "3" << endl;
}
void function()
{
cout << "4" << endl;
}
};
int main()
{
Father father;
Child child;
father.func();
father.function();
child.func();
child.function();
Father *fa = new Father();
fa = &father;
fa->func();
fa->function();
fa = &child;
fa->func();
fa->function();
return 0;
}
执行结果:1,2,3,4 1,2,1,4 3,2,3,4
执行结果可以看出,父类对象在调用function()函数时根据子类对象选择了不同的方法。
三、重载
1、 定义
重载是允许有多个同名的函数,但这些函数的参数列表不同,如参数个数不同和参数类型不同等。
重载与重写的区别就在于是否覆盖,重写一般多发生在不同的类且存在继承关系之间,而重载多是在一个类里或者一块代码段里。
2、 实现方式
重载函数的函数名必须相同,参数列表必须不同,返回值可以相同也可以不同。例如,void func(int num)和void func(string name)就属于重载。
3、 示例
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
void func(int num)
{
cout << num << endl;
}
void func(string name)
{
cout << name.c_str() << endl;
}
int main()
{
int num = 1;
string name = "liu";
func(num);
func(name);
return 0;
}
执行结果:1 liu
执行结果可以看出,在调用func()函数时会根据参数的不同选择相应的函数实现。
四、访问修饰符
1、 定义
public:所有范围都能访问;
protected:类自身和派生类能访问;
private:类自身能访问。