115 lines
13 KiB
HTML
115 lines
13 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh" dir="ltr" class="client-nojs" xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh">
|
|
<head><meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<title>抽象类</title>
|
|
<link rel="stylesheet" href="ext.css" />
|
|
<link rel="stylesheet" href="site_modules.css" />
|
|
</head>
|
|
<body class="mediawiki ltr sitedir-ltr ns-0 ns-subject page-cpp_language_abstract_class skin-cppreference2 action-view cpp-navbar">
|
|
<div id="cpp-content-base">
|
|
<div id="content"><a id="top"></a>
|
|
<h1 id="firstHeading" class="firstHeading">抽象类</h1>
|
|
<div id="bodyContent">
|
|
<div id="contentSub"><span class="subpages">< <a href="cpp.html">cpp</a>‎ | <a href="cpp-language.html">language</a></span></div>
|
|
<div id="mw-content-text" lang="zh" dir="ltr" class="mw-content-ltr" xml:lang="zh">
|
|
<p>定义不能被实例化,但可用作基类的抽象类型。</p>
|
|
<h3><span class="mw-headline" id=".E8.AF.AD.E6.B3.95">语法</span></h3>
|
|
<p>纯虚函数是其<a href="cpp-language-function.html">声明符</a>拥有下列语法的<a href="cpp-language-virtual.html">虚函数</a>:</p>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><span class="t-spar">声明符</span> <span class="t-spar">虚说明符</span><span class="t-mark">(可选)</span> <code><b>=</b></code> <code><b>0</b></code></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<p>在这里序列 <code><b>= 0</b></code> 被称作 <span class="t-spar">纯说明符</span>,且要么紧跟 <span class="t-spar">声明符</span> 之后,要么紧跟可选的 <span class="t-spar">虚说明符</span>(<a href="cpp-language-override.html">override</a> 或 <a href="cpp-language-final.html">final</a>)之后出现。</p>
|
|
<p><span class="t-spar">纯说明符</span> 不能在成员函数定义中出现。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">struct</span> Base <span class="br0">{</span> <span class="kw1">virtual</span> <span class="kw4">int</span> g<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="kw1">virtual</span> ~Base<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span><span class="br0">}</span> <span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw1">struct</span> A <span class="sy4">:</span> Base<span class="br0">{</span>
|
|
<span class="co1">// OK:声明三个成员虚函数,其中两个是纯虚函数</span>
|
|
<span class="kw1">virtual</span> <span class="kw4">int</span> f<span class="br0">(</span><span class="br0">)</span> <span class="sy1">=</span> <span class="nu0">0</span>, g<span class="br0">(</span><span class="br0">)</span> override <span class="sy1">=</span> <span class="nu0">0</span>, h<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="co1">// OK:析构函数也可以是纯虚函数</span>
|
|
~A<span class="br0">(</span><span class="br0">)</span> <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span>
|
|
<span class="co1">// 错误:函数定义中的纯说明符</span>
|
|
<span class="kw1">virtual</span> <span class="kw4">int</span> b<span class="br0">(</span><span class="br0">)</span><span class="sy1">=</span><span class="nu0">0</span> <span class="br0">{</span><span class="br0">}</span>
|
|
<span class="br0">}</span><span class="sy4">;</span></pre></div>
|
|
</div>
|
|
<p><span class="t-spar">抽象类(abstract class)</span> 是定义或继承了至少一个<a href="cpp-language-virtual.html">最终覆盖函数</a>是 <span class="t-spar">纯虚</span> 的函数的类。</p>
|
|
<h3><span class="mw-headline" id=".E8.A7.A3.E9.87.8A">解释</span></h3>
|
|
<p>抽象类用于表示一般性概念(例如 Shape、Animal 等),它可用作具体类(例如 Circle、Dog 等)的基类。</p>
|
|
<p>除了作为从其派生的类的基类子对象之外,不能创建抽象类的对象,且不能声明抽象类类型的非静态数据成员。</p>
|
|
<p>抽象类型不能用作形参类型,函数返回类型,或显式转换的类型(注意,这是在函数定义点和函数调用点检查的,因为在函数声明点其形参和返回类型可以是不完整类型)。</p>
|
|
<p>可以声明到抽象类的指针或引用。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">struct</span> Abstract <span class="br0">{</span>
|
|
<span class="kw1">virtual</span> <span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span> <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span> <span class="co1">// 纯虚</span>
|
|
<span class="br0">}</span><span class="sy4">;</span> <span class="co1">// "Abstract" 是抽象的</span>
|
|
|
|
<span class="kw1">struct</span> Concrete <span class="sy4">:</span> Abstract <span class="br0">{</span>
|
|
<span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span> override <span class="br0">{</span><span class="br0">}</span> <span class="co1">// 非纯虚</span>
|
|
<span class="kw1">virtual</span> <span class="kw4">void</span> g<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 非纯虚</span>
|
|
<span class="br0">}</span><span class="sy4">;</span> <span class="co1">// "Concrete" 不是非抽象的</span>
|
|
|
|
<span class="kw1">struct</span> Abstract2 <span class="sy4">:</span> Concrete <span class="br0">{</span>
|
|
<span class="kw4">void</span> g<span class="br0">(</span><span class="br0">)</span> override <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span> <span class="co1">// 纯虚覆盖函数</span>
|
|
<span class="br0">}</span><span class="sy4">;</span> <span class="co1">// "Abstract2" 是抽象的</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<span class="co1">// Abstract a; // 错误:不能创建抽象类的对象</span>
|
|
Concrete b<span class="sy4">;</span> <span class="co1">// OK</span>
|
|
Abstract<span class="sy3">&</span> a <span class="sy1">=</span> b<span class="sy4">;</span> <span class="co1">// OK:到抽象基类的引用</span>
|
|
a.<span class="me1">f</span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 虚派发到 Concrete::f()</span>
|
|
<span class="co1">// Abstract2 a2; // 错误:不能创建抽象类的对象(g() 的最终覆盖函数是纯虚的)</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<p>可以为纯虚函数提供定义(而且如果纯虚函数是<a href="cpp-language-destructor.html">析构函数</a>则必须提供):派生类的成员函数可以自由地用有限定的函数标识调用抽象基类的纯虚函数。此定义必须在类体之外提供(函数声明的语法不允许纯说明符 <code><b>= 0</b></code> 和函数体一起出现)。</p>
|
|
<p>从抽象类的构造函数或析构函数中进行纯虚函数的虚调用是未定义行为(无论纯虚函数是否拥有定义)。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="kw1">struct</span> Abstract <span class="br0">{</span>
|
|
<span class="kw1">virtual</span> <span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span> <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span> <span class="co1">// 纯虚</span>
|
|
<span class="kw1">virtual</span> <span class="kw4">void</span> g<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span><span class="br0">}</span> <span class="co1">// 非纯虚</span>
|
|
~Abstract<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
g<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// OK:调用 Abstract::g()</span>
|
|
<span class="co1">// f(); // 未定义行为</span>
|
|
Abstract<span class="sy4">::</span><span class="me2">f</span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// OK:非虚调用</span>
|
|
<span class="br0">}</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
|
|
<span class="co1">// 纯虚函数的定义</span>
|
|
<span class="kw4">void</span> Abstract<span class="sy4">::</span><span class="me2">f</span><span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"A::f()<span class="es1">\n</span>"</span><span class="sy4">;</span> <span class="br0">}</span>
|
|
|
|
<span class="kw1">struct</span> Concrete <span class="sy4">:</span> Abstract <span class="br0">{</span>
|
|
<span class="kw4">void</span> f<span class="br0">(</span><span class="br0">)</span> override <span class="br0">{</span>
|
|
Abstract<span class="sy4">::</span><span class="me2">f</span><span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// OK:调用纯虚函数</span>
|
|
<span class="br0">}</span>
|
|
<span class="kw4">void</span> g<span class="br0">(</span><span class="br0">)</span> override <span class="br0">{</span><span class="br0">}</span>
|
|
~Concrete<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
|
|
g<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// OK:调用 Concrete::g()</span>
|
|
f<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// OK:调用 Concrete::f()</span>
|
|
<span class="br0">}</span>
|
|
<span class="br0">}</span><span class="sy4">;</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E5.8F.82.E9.98.85">参阅</span></h3>
|
|
<ul>
|
|
<li><a href="cpp-language-virtual.html">virtual</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|