继承是面向对象程序设计中使代码可以复用的重要手段,可以允许在保持原有类特性的基础上对其进行扩展,从而产生新的类称作派生类。
多态是在不同的继承关系的类对象去调用同一函数而产生了不同的行为
通过定义和重写虚函数,通过基类的指针或引用指向派生类对象,通过基类的指针或引用调用虚函数实现多态。(调用相同接口,表现不同结果)
虚函数被virtual修饰的类成员函数(就是允许派生类对其进行重写)
虚函数的重写:在派生类中的一个与基类虚函数完全相同的虚函数,即返回类型、函数名与参数列表完全相同。
虚析构 即在析构函数前加上virtual关键字虚析构主要可以用于解决内存泄露的问题,如果delete p 的时候,只会看p的赋值对象,如果对象基类的话就调用基类的析构函数,如果对象是派生类,就会调用派生类的虚构函数然而 ,若没有虚析构,在delete p 的时候就只会看指针的数据类型,所以会有内存泄漏的问题,这种情况也可以使用智能指针来解决,智能指针会自己调用析构函数。
继承有三种方式
1.私有继承 基类中的保护和公有成员在派生类中变成了私有成员,在派生类中可以直接访问,基类中的私有成员虽然被继承下来了,但在派生类中不可直接访问,但是派生类的对象不可以访问到基类中的任何成员,由于父类的公有成员和保护成员继承到派生类之后都变成了私有成员只能由直接派生子类访问,无法再往下继承
2.保护继承基类中的公有和保护成员在派生类中变成了保护成员,在派生类中可直接访问,基类的私有成员虽然被继承下来,但在派生类中不可直接访问,但是派生类的对象不能访问到基类的任何成员,因为在保护继承的时候基类的公有和保护都成为了派生类的保护成员
3.共有继承基类中的公有和保护成员在派生类中仍为公有和保护成员,在派生类中可直访问,基类的私有成员虽然被继承下来但在派生类中不可直接访问,派生类的对象可以访问到基类的公有成员,不能访问到基类的保护和私有成员
#include<iostream>
#include<string>
using namespace std;
class Object
{
private:
int value;
public:
Object(int x = 0){value=x;}
string Getname(){string na = "ylq";return na;}
protected:
string Getsex(){string sex = "nan";return sex;}
};
//公有继承
class Base :public Object
{
public:
Base():Object(0){};
string GetBname(){return Getname();}//可以访问到基类的公有成员和保护成员
protected:
string GetBsex(){return Getsex();}
};
//私有继承
class Child:private Object
{
private:
Child():Object(0){}
string GetCname(){return Getname();}//在派生类中也可以访问到基类中的共有和保护成员
string GetCsex(){return Getsex();}
};
//保护继承
class Item:protected Object
{
protected:
Item():Object(0){}
string GetInaem(){return Getname();}//在派生类中也可以访问到基类中的保护和公有成员
string GetIsex(){return Getsex();}
};
int main()
{
Base a1;
a1.value;//error 不可访问
a1.Getname();//ok可以访问到基类中的共有成员
a1.Getsex();//error 不可访问
Child a2;
a2.value;//error
a2.Getname();//error
a2.Getsex();//error
Item a3;
a3.value;//error
a3.Getname();//error
a3.Getsex();//error
}
在虚函数的问题中还有一点需要注意的就是:当一个空类型中 一旦产生了一个虚函数,那么在这个类中就会产生虚函数表,并且产生一个指针使该类型的实例去指向这个虚函数表,而这个指针的大小四个字节或者八个字节