虚函数与多态
C++的多态性包括:
(1)编译时多态(静态多态):函数重载、运算符重载、模板实现
(2)运行时多态(动态多态):虚函数实现
虚函数的概念:
在某基类中声明为virtual并在一个或多个派生类中被重新定义的成员函数。用法格式:virtual 函数返回类型 函数名 (参数表) {函数体} 。作用为通过指向派生类的基类指针或引用来操作对象。
Inheritance(继承)with virtual function(虚函数)
(1)non-virtual函数:你不希望derived class重新定义(override,覆写)它。
(2)virtual函数:你希望derived class重新定义(override,覆写)它,且你对它已有默认定义。
(3)pure virtual函数:你希望derived class一定要重新定义(override,覆写)它,你对它没有默认定义。在基类中实现纯虚函数的方法是在函数原型后面加“= 0”
通过下面的程序来认识一下这三种函数:
class Shape
{
public:
virtual void draw() const = 0; //纯虚函数
virtual void error(const std::string& msg); //虚函数
int objectID() const; //非虚函数
...
};
class Rectangle:public Shape{...}; //继承
class Ellipse:public Shape{...}; //继承
下面来看一个简单的例子:
using namespace std;
class A
{
public:
A(){};
~A(){};
void showMe()
{
cout << "A" << endl;
}
};
class B : class A
{
public:
B(){};
~B(){};
void showMe()
{
cout << "B" <<endl;
}
};
int main(int argc, char const* argv[])
{
A *p1 = new A;
A *p2 = new B;
p1 -> showMe();
p2 -> showMe();
return 0;
}
该段程序运行的结果是“A”“A”。问题是p2明明指向的是class B的对象,可是调用的却是class A的showMe()函数,这是我们不希望得到的结果。解决这个问题就需要用到虚函数。
using namespace std;
class A
{
public:
A(){};
~A(){};
virtual void showMe()
{
cout << "A" << endl;
}
};
class B : class A
{
public:
B(){};
~B(){};
virtual void showMe()
{
cout << "B" <<endl;
}
};
int main(int argc, char const* argv[])
{
A *p1 = new A;
A *p2 = new B;
p1 -> showMe();
p2 -> showMe();
return 0;
}
此时再运行,输出的结果为“A”“B”。加上virtual关键字后,基类的成员函数showMe()变成虚函数,自然地派生类的showMe()也自动变成虚函数。对于派生类的响应函数前是否需要加virtual关键字,则都可以。
总结一下就是:当基类指针指向一个子类对象,通过这个指针调用子类中和基类同名的函数时,如果基类中声明为虚函数(子类不写也可以)就会调用子类的这个函数(覆写的概念),如果基类中没有声明为虚函数就会调用基类的函数。
上一篇: C++之共有继承、保护继承、私有继承
下一篇: 单链表实现集合的交并差运算
推荐阅读
-
Python中函数的参数传递与可变长参数介绍
-
PHP用mb_string函数库处理与windows相关中文字符及Win环境下开启PHP Mb_String方法
-
.net中前台javascript与后台c#函数相互调用问题
-
python 常见字符串与函数的用法详解
-
html5 Web SQL Database 之事务处理函数transaction与executeSQL解析
-
php小经验:解析preg_match与preg_match_all 函数
-
html5 Web SQL Database 之事务处理函数transaction与executeSQL解析
-
C#虚函数用法实例分析
-
php中eval函数的危害与正确禁用方法
-
浅谈SQLServer的ISNULL函数与Mysql的IFNULL函数用法详解