一、简介
virtual 在英文中表示 “虚”、“虚拟” 的含义。
C++ 中的关键字 “virtual” 主要用在两个方面:虚函数和虚基类。
二、虚函数与虚基类
1. 虚函数
虚函数是多态的一种。
在C++中,基类的指针或引用可以指向或引用派生类对象。
派生类可以重写基类中的成员函数。
{
class base
{
public:
void test(){ cout << “基类方法”; }
};
class inheriter:public base
{
public:
void test(){ cout << “派生类方法”; }
};
}
可以在基类中将被重写的成员函数设置为虚函数,其含义是:“当通过基类的指针或引用调用该成员函数时,将根据指针指向的对象类型确定调用的函数,而非指针的类型。”
{
base* p1 = new base;
base* p2 = new inheriter;
p1->test();
p2->test();
}
将test() 函数设置为vritual 后:
{
base* p1 = new base;
base* p2 = new inheriter;
p1->test();
p2->test();
}
如此,便可以将基类和派生类的同名方法区分开,实现多态。
说明:
一、只需将基类中的成员函数声明为虚函数即可,派生类中重写的virtual函数自动成为虚函数;
二、 基类中的析构函数必须为虚析构函数,否则会出现对象释放错误。以上例说明,如果不将其基类的析构函数声明为virtual,那么在调用delete p2;语句时将调用基类的析构函数,而不是应当调用的派生类的析构函数,从而出现对象释放错误的问题。
三、 虚函数的使用将导致类对象占用更大的内存空间。对这点的解释涉及到虚函数调用的原理:编译器给每一个包括虚函数的对象添加了一个隐藏成员:指向虚函数表的指针。
四、重写函数的特征标必须与基类函数一致,否则将覆盖基类函数。
2. 虚基类
在C++中,派生类可以继承多个基类。
- 问题在于:如果这多个基类又是继承同一个基类时,那么派生类是不是需要多次继承这“同一个基类”的内容?这时候虚基类的作用就发挥出来了。
- 虚基类可以使得继承同一个基类的派生类们的派生类对象只继承一个对象。
虚继承写法:**
class 派生类名:virtual [访问符] 基类名 - base称为mytest1类的虚基类。假设base还是另外一个类mytest2的虚基类,对于多重继承mytest1和mytest2的子类mytest3而言,base的部分只继承了一次。
class base
{
public:
int b;
virtual void test(void)
{
std::cout << “base’s test”;
return;
}
virtual ~base(){ };
};
class mytest1:virtual public base{ };
class mytest2:virtual public base{ };
class mytest3:public mytest1, public mytest2{ };
std::cout << sizeof(mytest1) << “\”;
std::cout << sizeof(mytest2) << “\”;
std::cout << sizeof(mytest3) << std::endl;;
//输出
//12\12\16
程序说明:
一、mytest1类与mytest2类的大小为什么是12?这是因为它们在虚继承base类后,添加了一个隐藏的成员—指向虚基类的指针,占?1 个字节,而base类本身占?2 个字节,因此它们的大小均为?3 ,而对非虚继承而言,是不需要这样的一个指针的。mytest3类的大小为:
sizeof(base) + sizeof(mytest1 - base) + siezeof(mytest2 - base),即?4 字节。