目录
- 一、概念及定义
- 二、虚函数重写的特例
- 三、final和override
- 四、抽象类
一、概念及定义
概念:在继承关系下的不同类,调用同一个函数,产生不同的行为,叫作多态。
图示:
定义:必须通过基类的指针或者引用调用虚函数;被调用的函数必须是虚函数。类里的函数的返回类型前加上virtual就是虚函数,子类继承父类的虚函数叫作重写,重写的是虚函数的实现,该虚函数的返回类型、函数名、参数列表都要与父类相同(有两个特例,后面再谈)。
class Person
{
public:
virtual void func()
{
cout << "全价" << endl;
}
};
class Student :public Person
{
public:
virtual void func()
{
cout << "半价" << endl;
}
};
void test1(Person* ps)//通过基类的指针
{
ps->func();//调用虚函数
}
void test2(Person& ps)//通过基类的引用
{
ps.func();//调用虚函数
}
int main()
{
Person p;
Student s;
test1(&p);
test1(&s);
test2(p);
test2(s);
return 0;
}
注:子类的虚函数加不加virtual都没关系,但是父类一定要有virtual,否则就不是虚函数了。一般为了规范,子类也最好加上virtual
二、虚函数重写的特例
1️⃣协变
父子类的虚函数返回类型可以不相同。基类虚函数返回基类对象的指针或者引用,派生类虚函数返回派生类对象的指针或者引用。
class A {};
class B : public A {};
class Person {
public:
virtual A* f()
{
return new A;
}
};
class Student : public Person {
public:
virtual B* f()
{
return new B;
}
};
2️⃣析构函数的重写
如果基类的析构函数是虚函数,只要派生类的析构函数定义了,不管加不加virtual,都是虚函数。两个析构函数的函数名不相同也构成重写,因为编译器有作特殊处理,编译后析构函数的名称统一处理成destructor。
class Person
{
public:
virtual ~Person()
{
cout << "~Person()" << endl;
}
};
class Student :public Person
{
public:
virtual ~Student()
{
cout << "~Student()" << endl;
}
};
int main()
{
Person* p = new Person;
Person* s = new Student;
delete p;
delete s;
return 0;
}
三、final和override
1️⃣final关键字修饰虚函数,该虚函数不能被重写
2️⃣override关键字是用来检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错。
四、抽象类
概念:包含纯虚函数的类叫抽象类。纯虚函数:在虚函数的后面写上 =0,就称为纯虚函数。抽象类不能实例化对象,继承它的派生类只有重写纯虚函数才能实例化出对象。
class Animal
{
public:
virtual void Action() = 0;//抽象类,纯虚函数声明即可
};
class Dog :public Animal
{
public:
virtual void Action()//对纯虚函数进行重写
{
cout << "running!" << endl;
}
};
class Bird :public Animal
{
public:
virtual void Action()//对纯虚函数进行重写
{
cout << "flying!" << endl;
}
};
int main()
{
Animal* d = new Dog;
Animal* b = new Bird;
d->Action();
b->Action();
return 0;
}