1、该函数必须与基类的虚函数有相同的名称
2、该函数必须与基类的虚函数有相同的参数个数和相对应的参数类型
3、该函数必须与基类的虚函数有相同的返回值,或满足类型兼容规则的指针,引用型返回值。
4、如果派生类的函数满足以上三个条件系统就会自动把其定为虚函数。这时派生类的虚函数便覆盖了基类的虚函数,不仅如此派生类中的虚函数还会隐藏基类中同名函数的所有其他重载形式。
5、只有虚函数是动态绑定的,如果派生类需要修改基类的行为,即重写与基类的函数同名的函数,就应该在基类中将相应的函数声明为虚函数。而基类中声明的非虚函数,通常代表不希望被派生类改变的功能,也不能实现多态。因此一般不要重写继承而来的非虚函数。
6、在重新继承来的虚函数时,如果有默认形参值,千万不要定义不同的值。原因是谁然虚函数是动态绑定的,但是默认形参值是静态绑定的,也就是说,通过一个指向派生类对象的基类指针,可以访问到派生类的虚函数,但默认形参值却只能来自基类的定义;
// VirtualAndDT.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
using namespace std;
//虚函数经典列子
class B0
{
public:
virtual void display()//如果没有虚函数 下面的main函数内容将输出都是基类的函数
{
cout <<"我是显示页面B0" << endl;
}
};
class B1:public B0
{
public:
void display()
{
cout << "我是显示页面B1" << endl;
}
};
void fun(B0 *p)
{
p->display();
}
void main()
{
B0 *p;//基类指针
B0 b0;
B1 b1;
p = &b0;
fun(p);
p = &b1;
fun(p);
system("pause");
}
虚函数是动态绑定的,但是默认形参值是静态绑定的,也就是说,通过一个指向派生类对象的基类指针,可以访问到派生类的虚函数,但默认形参值却只能来自基类的定义
// VirtualAndDT.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
using namespace std;
//虚函数
class B0
{
public:
virtual void display(int a=5)
{
cout << "我是显示页面B0" << a << endl;
}
};
class B1:public B0
{
public:
void display(int a=6)
{
cout << "我是显示页面B1" << a << endl; // 注意输出是 5
}
};
class B2:public B1
{
public:
void display(int a = 7) // 注意输出是5
{
cout << "我是显示页面B2" << a<< endl;
}
};
void fun(B0 *p)
{
p->display();
}
void main()
{
B0 *p;
B0 b0;
B1 b1;
B2 b2;
p = &b0;
fun(p);
p = &b1;
fun(p);
p=&b2;
fun(p);
system("pause");
}
// VirtualAndDT.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
using namespace std;
class B0
{
public:
virtual void display() //显示定义虚函数
{
cout << "我是显示页面B0" << endl;
}
};
class B1:public B0
{
public:
void display() //默认虚函数
{
cout << "我是显示页面B1" << endl;
}
};
class B2:public B1
{
public:
void display()
{
cout << "我是显示页面B2" << endl;
}
};
void fun(B0 *p)
{
p->display();
}
void main()
{
B0 *p;
B0 b0;
B1 b1;
B2 b2;
p = &b0;
fun(p);
p = &b1;
fun(p);
p=&b2;
fun(p);
system("pause");
}
二、纯虚函数
纯虚函数是在基类中只声明虚函数而不给出具体的函数定义体,将它的具体定义放在各派生类中,称此虚函数为纯虚函数.通过该基类的指针或引用就可以调用所有派生类的虚函数,基类只是用于继承,仅作为一个接口,具体功能在派生类中实现.
纯虚函数的声明如下:(注:要放在基类的定义体中)
virtual 函数原型=0;
声明了纯虚函数的类,称为抽象类。
-
抽象类中可以有多个纯虚函数
-
不能声明抽象类的对象,但可以声明指向抽象类的指针变量和引用变量
-
抽象类也可以定义其他非纯虚函数
-
如果派生类中没有重新定义基类中的纯虚函数,则在派生类中必须再将该虚函数声明为纯虚函数
-
从抽象类可以派生出具体或抽象类,但不能从具体类派生出抽象类
-
在一个复杂的类继承结构中,越上层的类抽象程度越高,有时甚至无法给出某些成员函数的实现,显然,抽象类是一种特殊的类,它一般处于类继承结构的较外层
-
引入抽象类的目的,主要是为了能将相关类组织在一个类继承结构中,并通过抽象类来为这些相关类提供统一的操作接口
class B0
{
public:
virtual void display() const =0;//如果没有纯虚函数 下面的main函数内容将输出都是基类的函数
};
class B1:public B0
{
public:
void display() const
{
cout << "我是显示页面B1" << endl;
}
};
void fun(B0 *p)
{
p->display();
}
void main()
{
B0 *p;
//B0 b0;
//error C2259: “B0”: 不能实例化抽象类
B1 b1;
//p = &b0;
//fun(p);
p = &b1;
fun(p);
system("pause");
}
/*
virtual void display() const =0;//纯虚函数
(1)=0说明它是纯虚函数
(2)const表明不能修改其数据成员
const 和 =0 没有关系,要分开理解
成员函数后面用 const 修饰,通俗的理解就是在这个函数内不能修改类的成员变量,除非那个成员变量是 mutable 的
*/
class B1:public B0
{
public:
void display() const
{
cout << "我是显示页面B1" << endl;
x = 0;
/*error C2166: 左值指定 const 对象*/
}
private:
int x;
};
转载自原文链接, 如需删除请联系管理员。
原文链接:一步一步学习C++(类)之虚函数和纯虚数,转载请注明来源!