虚函数为了重载和多态:父类和子类之间的关系
多态:基类指针形参/变量接受一个派生类的地址实参/变量,通过基类指针可以调用派生类的虚函数重载。
class Base{
public:
virtual void print_test(){cout<<"Base"<<endl;}
};
class derived : public Base{
public:
virtual void print_test(){cout<<"derived"<<endl;} //函数(重写)
};
void print_fun(Base* ptr){ //多态实现
ptr->print_test(); //实参是Base就输出Base,实参是derived就输出derived
}
纯虚函数:子类与子类之间的关系
因为在父类中纯虚函数(接口)没有实现,这样做的原因就是派生出多个子类时候,都通过接口来完成各自的操作,换句话说
如果从抽象类派生若干子类,则这些子类必须都要使用抽象类中定义的那些纯虚函数,因为纯虚函数必须在子类里面重写,不然
没办法创建子类对象(如果不在派生类中重写基类的纯虚函数,则派生类也是一个抽象类,抽象类只能创建引用指针)
重载: 函数名相同,参数列表不同(返回值类型不能作为判断重载的标志),重载出现在一个类的内部。
重写:子类中重新定义父类中有相同名称和参数的虚函数,出现在继承关系中。
1.被重写的函数必须是virtual的不能是static
2.被重写后的函数跟之前的必须:返回值,函数名,参数列表都一样
3.访问权限可以改变,重写后可以改为protected,private等
重定义:子类中重新定义父类中非virtual函数, 参数列表跟重定义前的不一致也叫重定义,靠函数名保证;也叫隐藏
1.调用的时候可以强制转换成父类类型来调用。
纯虚函数和虚函数都能实现 ”不同的子类具有不同的操作“ 这样一个特性;
父类的纯虚函数必须在子类中“重写”, 父类的虚函数在子类中可以不“重写”, 也可以“重写”。
别人的栗子:https://blog.youkuaiyun.com/lanchunhui/article/details/50704957
#include <iostream>
class Animal
{
public:
virtual void make_sound() const = 0;
virtual void make_sound2() const = 0;
// 纯虚函数
virtual void swim() const{}
virtual void run() const{}
// 虚函数
void say() const { std::cout << "I'm a happy little animal, I live on the earth." << std::endl; }
// 普通函数
};
class Dog: public Animal
{
public:
void make_sound() const
{
std::cout << "wang! wang! wang wang!!" << std::endl;
}
void make_sound2() const {}
void run() const
{
std::cout << "I'm a dog, I can run!" << std::endl;
}
};
class Fish :public Animal
{
public:
void make_sound() const
{
std::cout << "wen! wen! wenwen!" << std::endl;
}
void make_sound2() const
{
std::cout<<"test, test!!!"<<std::endl;
}
void swim() const
{
std::cout << "I'm a fish, I can swim." << std::endl;
}
};
void fun(Animal* p){
std::cout<<"in function"<<std::endl;
p->make_sound();
p->make_sound2();
}
int main(int, char**)
{
Fish ff;
fun(&ff);
Animal* fp;
fp = new Fish();
fp->swim();
fp->say();
fp->run();
fp->make_sound();
//fp->make_sound2();
fp=new Dog();
fp->run();
fp->make_sound2();
return 0;
}