📄 purevirtualfunction.html
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link rel="stylesheet" href="css/stdlayout.css" type="text/css">
<link rel="stylesheet" href="css/print.css" type="text/css">
<meta content="text/html; charset=gb2312" http-equiv="content-type">
<title>纯虚拟函式、抽象类别(Abstract class)</title>
</head>
<body>
<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>
<h1><a href="CppGossip.html">C++
Gossip: 纯虚拟函式、抽象类别(Abstract class)</a></h1>
C++预设函式成员都不是虚拟函式,如果要将某个函式成员宣告为虚拟函式,则要加上"virtual"关键字,然而C++提供一种语法定义“纯虚拟函式”
(Pure virtual
function),指明某个函式只是提供一个介面,要求继承的子类别必须重新定义该函式,定义纯虚拟函式除了使用关键字"virtual"之外,要在函
式定义之后紧跟着'='并加上一个0,例如:<br>
<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">class Some {</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">public:<br>
// 纯虚拟函式<br style="font-weight: bold;">
virtual void someFunction() = 0;</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> ....</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">};</span><br>
</div>
<br>
一个类别中如果含有虚拟函式,则该类别为一“抽象类别”(Abstract class),该类别只能被继承,而不能用来直接生成实例,如果试图使用一个抽象类别来生成实例,则会发生编译错误。<br>
<br>
以下举个实际的例子,先假设您设计了两个类别:ConcreteCircle与HollowCircle:<br>
<div style="margin-left: 40px; font-weight: bold; font-family: Courier New,Courier,monospace;">class ConcreteCircle {<br>
public:<br>
void radius(double radius) {<br>
_radius = radius;<br>
}<br>
double radius() {<br>
return _radius;<br>
}<br>
void render() {<br>
cout << "画一个半径 " <br>
<< _radius <br>
<< " 的实心圆"<br>
<< endl;<br>
}<br>
private:<br>
double _radius;<br>
};<br>
</div>
<br style="font-family: Courier New,Courier,monospace;">
<br style="font-family: Courier New,Courier,monospace;">
<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">class HollowCircle {</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">public:</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> void radius(double radius) {</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> _radius = radius;</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> }</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> double radius() {</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> return _radius;</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> }</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> void render() {</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> cout << "画一个半径 " </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> << _radius </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> << " 的空心圆"</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> << endl;</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> }</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">private:</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> double _radius;</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">};</span><br>
</div>
<br>
显然的,这两个类别除了render()方法的实作内容不同之外,其它的定义是一样的,而且这两个类别所定义的显然都是“圆”的一种类型,您可以定义一个
抽象的AbstractCircle类别,将ConcreteCircle与HollowCircle中相同的行为与定义提取(Pull
up)至抽象类别中:<br>
<ul>
<li>AbstractCircle.h</li>
</ul>
<pre>#ifndef ABSTRACTCIRCLE<br>#define ABSTRACTCIRCLE<br><br>class AbstractCircle {<br>public:<br> void radius(double radius) {<br> _radius = radius;<br> }<br> double radius() {<br> return _radius;<br> }<br> // 宣告虚拟函式<br> virtual void render() = 0;<br> <br>protected:<br> double _radius;<br>};<br><br>#endif</pre>
<span class="postbody"><br>
注意到在类别宣告了虚拟函式render(),所以AbstractCircle是个抽象类别,它只能被继承,继承了AbstractCircle的类别
必须实作render()函式,接着您可以让ConcreteCircle与HollowCircle类别继承AbstractCircle方法并实作
render()函式:<br>
</span>
<ul>
<li>HollowCircle.h</li>
</ul>
<pre>#include <iostream> <br>#include "AbstractCircle.h"<br>using namespace std; <br><br>class HollowCircle : public AbstractCircle {<br>public:<br> void render() {<br> cout << "画一个半径 " <br> << _radius <br> << " 的空心圆"<br> << endl;<br> }<br><br>};</pre>
<ul>
<li>ConcreteCircle.h</li>
</ul>
<pre>#include <iostream> <br>#include "AbstractCircle.h"<br>using namespace std; <br><br>class ConcreteCircle : public AbstractCircle {<br>public:<br> void render() {<br> cout << "画一个半径 " <br> << _radius <br> << " 的实心圆"<br> << endl;<br> }<br><br>};</pre>
<span class="postbody"><br>
由于共同的定义被提取至AbstractCircle类别中,并于衍生类别中继承了下来,所以在ConcreteCircle与HollowCircle
中无需重覆定义,只要定义个别对render()的处理方式就行了,而由于ConcreteCircle与HollowCircle都是
AbstractCircle的子类别,因而可以使用AbstractCircle上所定义的虚拟操作介面,来操作子类别实例上的方法,如下所示:<br>
</span>
<ul>
<li>main.cpp</li>
</ul>
<pre>#include <iostream> <br>#include "AbstractCircle.h"<br>#include "ConcreteCircle.h"<br>#include "HollowCircle.h"<br>using namespace std; <br><br>void render(AbstractCircle &circle) {<br> circle.render();<br>}<br><br>int main() {<br> ConcreteCircle concrete;<br> concrete.radius(10.0);<br> render(concrete);<br> <br> HollowCircle hollow;<br> hollow.radius(20.0);<br> render(hollow);<br> <br> return 0;<br>}<br></pre>
<span class="postbody"><br>
执行结果:</span><br>
<table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td style="background-color: rgb(0, 0, 0);"><small><span style="color: rgb(255, 255, 255);">画一个半径 10 的实心圆<br>
画一个半径 20 的空心圆</span></small><span style="color: rgb(255, 255, 255);"><br>
</span></td>
</tr>
</tbody>
</table>
<br>
<br>
<br>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -