⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 classabc.html

📁 关于 C++ 的历史无须我来介绍了
💻 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>简介类别(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: 简介类别(Class)</a></h1>

class是C++中用来封装资料的关键字,当您使用类别来定义一个物件(Object)时,您考虑这个物件可能拥有的“属性”(Property)与
“方法”(Method),属性是物件的静态描述,而方法是可施加于物件上的动态操作,您使用类别定义出这个物件的规格书,之后就可依这个规格书制作出一
个个的物件实例,并在制作过程中设定个别物件的专属特性资料。 <br>

<br>

举个例子来说,您可以定义一个“球”的模子,考虑球有各种不同的颜色(或名称),以及球最基本的球半径资讯,您想到这些资讯应该可以取得,并可以进一步取
得球的体积,当您在C++中要包装这些资讯时,您可以如下进行定义: <br>

<ul>

  <li>Ball.h</li>

</ul>

<pre>#include &lt;string&gt;<br>using namespace std;<br><br>class Ball { <br>public: <br>    Ball(); <br>    Ball(double, const char*);     <br>    Ball(double, string&amp;); <br>    <br>    double radius();<br>    string&amp; name(); <br>    <br>    void radius(double);  <br>    void name(const char*);     <br>    void name(string&amp;); <br>    <br>    double volumn(); <br><br>private:<br>    double _radius; // 半径 <br>    string _name;  // 名称 <br>};</pre>

<br>

您在表头档案中定义类别,表头档案的名称建议与类别名称同名,一个定义良好的类别,即使在不看程式码实作的情况下,也可以从定义中看出这个类别的大致功
能;class是C++中用来定义类别的关键字,Ball是我们取得类别名称,记得一个类别的定义是这么作的: <br>

<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">class Ball { </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">

<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp; &nbsp; //
成员定义</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>

最重要的是别忘了在最后加上分号,初学C++的新手很常犯这个错误;接下来定义类别的成员,注意到public这个关键字,它表示以下所定义的成员可以使
用物件名称直接被呼叫,也称之为“公用成员”或“公开成员”,private关键字下的则是“私用成员”或“私有成员”,不可以透过物件名称直接呼叫。<br>

<br>

在类别封装时,有一个基本原则是:资讯的最小化公开。如果属性可以不公开就不公开,如果要取得或设定物件的某些属性,也是尽量透过方法成员来进行。 <br>

<br>

资讯的最小化公开原则是基于安全性的考量,避免程式设计人员随意操作属性成员而造成程式的错误,您可以在日后的程式设计中慢慢来体会;在稍后的实作中,您
将可以看到,我将不会radius与name两个私用成员直接进行存取,而是透过公开的方法来进行设定。 <br>

<br>

接下来实作类别的内容: <br>

<ul>

  <li>Ball.cpp</li>

</ul>

<pre>#include &lt;string&gt;<br>#include "Ball.h"<br>using namespace std;<br><br>// 预设建构函式<br>Ball::Ball() {<br>    _radius = 0.0; <br>    _name = "noname ball";    <br>}<br><br>Ball::Ball(double radius, const char *name) { <br>    _radius = radius; <br>    _name = name;<br>}<br><br>Ball::Ball(double radius, string &amp;name) { <br>    _radius = radius; <br>    _name = name;<br>}<br><br>double Ball::radius() { <br>    return _radius; <br>} <br><br>double Ball::volumn() { <br>    return (4 / 3 * 3.14159 * _radius * _radius * _radius); <br>} <br><br>string&amp; Ball::name() { <br>    return _name; <br>} <br><br>void Ball::radius(double radius) { <br>    _radius = radius; <br>} <br><br>void Ball::name(string &amp;name) { <br>    _name = name; <br>}<br><br>void Ball::name(const char *name) { <br>    _name = name; <br>}</pre>

<br>

类别的实作档案通常与类别名称同名,如此例中的Ball.cpp,与类别名称同名的方法称之为“建构函式”(Constructor),也有人称之为“建
构子”,它没有传回值,建构函式的作用在于物件生成时自动初始一些必要的资讯,它可以被过载,以满足物件生成时不同的设定条件。 <br>

<br>

“::”称之为类别范围解析(Class scope
resolution)运算子,在实作类别方法时,在::之前指明您要实作的是哪一个类别的方法,您在实作中过载了建构函式,在不指定引数的情况下,会将
radius设定为0,而name设定为"noname
ball",另两个建构函式则可以指定引数,无参数数建构函式是预设建构函式,如果您没有定义预设建构函式,则编译器会自动帮您产生一个无实作内容的预设
建构函式。<br>

<br>

定义好类别之后,您就可使用这个类别来建立物件,例如: <br>

<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">Ball ball1; </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">

<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">Ball ball2(5.0,
"black ball");</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">

<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">string
name("yellow ball");</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">

<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">Ball ball3(10.0,
name);</span><br>

</div>

<br>

也可以这么建立物件:<br>

<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">Ball ball1 = Ball(5.0,
"black ball");</span><br>

</div>

<br>

这有些类似宣告变数,使用类别建立的变数称其为“物件”(Object)或“实例”(Instant),在上例中就是ball1、ball2与ball3
三个物件,ball1物件在建立时并不指定任何参数,所以根据之前实例建构函式的内容,b1的radius将设定为0.0,name设定为"noname
ball";ball2则给定两个参数,所以ball2的radius设定为5.0,而ball2的name设定为"black
ball";ball3则是给定radius引数为10.0,第二个参数则给定string实例。 <br>

<br>

您可以透过公开成员来操作物件或取得物件资讯,方法是使用物件名称加上“.”运算子,例如: <br>

<div style="margin-left: 40px; font-family: Courier New,Courier,monospace;"><span style="font-weight: bold;">ball1.name("green
ball");</span><br>

</div>

<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">cout &lt;&lt;
ball1.name() &lt;&lt; endl;</span><br>

<br>

</div>

以下是使用Ball类别的一个实际例子:<br>

<ul>

  <li>main.cpp</li>

</ul>

<pre>#include &lt;iostream&gt; <br>#include "Ball.h"<br>using namespace std; <br><br>int main() {<br>    Ball ball1;<br>    cout &lt;&lt; ball1.name() &lt;&lt; "\t"<br>         &lt;&lt; ball1.volumn() <br>         &lt;&lt; endl;<br>    <br>    ball1.name("green ball");<br>    ball1.radius(2.5);<br>    cout &lt;&lt; ball1.name() &lt;&lt; "\t"<br>         &lt;&lt; ball1.volumn() <br>         &lt;&lt; endl;<br><br>    Ball ball2(5.0, "black ball");<br>    cout &lt;&lt; ball2.name() &lt;&lt; "\t"<br>         &lt;&lt; ball2.volumn() <br>         &lt;&lt; endl;    <br>             <br>    string name("yellow ball");<br>    Ball ball3(10.0, name);<br>    <br>    cout &lt;&lt; ball3.name() &lt;&lt; "\t"<br>         &lt;&lt; ball3.volumn() <br>         &lt;&lt; endl;<br>         <br>    return 0; <br>}<br></pre>

<br>

<span class="postbody">
执行结果:</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);">noname ball&nbsp;&nbsp;&nbsp;&nbsp;
0<br>

green ball&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;49.0873<br>

black ball&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; 392.699<br>

yellow ball&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 3141.59</span></small><span style="color: rgb(255, 255, 255);"><br>

      </span></td>

    </tr>

  
  </tbody>
</table>

<br>

对于简单的成员函式,您可以将之实作于类别定义中,在类别定义中即实作的函式会自动成为inline函式,例如:<br>

<ul>

  <li>Ball.h</li>

</ul>

<pre>#include &lt;string&gt;<br>using namespace std;<br><br>class Ball { <br>public: <br>    Ball(); <br>    Ball(double, const char*);     <br>    Ball(double, string&amp;); <br>    <br>    // 实作于类别定义中的函式会自动inline<br>    double radius() {<br>        return _radius;<br>    }<br>    <br>    string&amp; name() {<br>        return _name; <br>    }<br>    <br>    void radius(double radius) {<br>         _radius = radius;<br>    } <br>    <br>    void name(const char *name) {<br>         _name = name;<br>    }<br>        <br>    void name(string&amp; name) {<br>         _name = name;<br>    }<br>    <br>    double volumn() {<br>        return (4 / 3 * 3.14159 * _radius * _radius * _radius); <br>    }<br>    <br>private:<br>    double _radius; // 半径 <br>    string _name;  // 名称 <br>};</pre>

<br>

<ul>

  <li>Ball.cpp</li>

</ul>

<pre>#include &lt;string&gt;<br>#include "Ball.h"<br>using namespace std;<br><br>// 预设建构函式<br>Ball::Ball() {<br>    _radius = 0.0; <br>    _name = "noname ball";    <br>}<br><br>Ball::Ball(double radius, const char *name) { <br>    _radius = radius; <br>    _name = name;<br>}<br><br>Ball::Ball(double radius, string &amp;name) { <br>    _radius = radius; <br>    _name = name;<br>}</pre>

<br>

在定义类别时,如果您只是需要使用到某个类别来宣告指标或是参考,但不涉及类别的生成或操作等讯息,则您可以作该类别的前置宣告(Forward
declaration),而不用含入该类别的定义,例如:<br>

<ul>

  <li>Test.h</li>

</ul>

<pre>class Ball;<br><br>class Test { <br>public:<br>    Test();<br>    Test(Ball*); <br>    <br>    Ball* ball(); <br>    void ball(Ball*);<br><br>private:<br>    Ball *_ball;  // 名称 <br>};<br></pre>

<br>

在定义Test类别时,您尚未真正使用Ball来建构物件进行操作,您只是用它来宣告一些名称,则您只要使用前置宣告就可以了,实际实作类别时再含入
Ball.h表头档即可,例如:<br>

<ul>

  <li>Test.cpp</li>

</ul>

<pre>#include "Test.h"<br>#include "Ball.h"<br><br>Test::Test() { <br>    _ball = new Ball;<br>}<br><br>Test::Test(Ball *ball) {<br>    _ball = ball;<br>}<br><br>Ball* Test::ball() {<br>    return _ball;<br>}<br><br>void Test::ball(Ball *ball) {<br>    _ball = ball;     <br>}<br></pre>

<br>

如果您的类别定义有单一参数的建构函式(或除了第一个参数之外,其它参数都有预设值的建构函式),则预设会有自动转换的作用,例如:<br>

<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">class Ball { </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;">&nbsp;&nbsp;&nbsp;
Ball(const char*); </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">

<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp; &nbsp;...</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>

则您可以使用以下的方式来建构物件并初始化:<br>

<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">Ball ball&nbsp;= "Green
ball";</span><br>

</div>

<br>

预设的转换行为是由编译器施行的,但有时是有危险的,如果您不希望编译器自作主张,则您可以使用explicit修饰,告诉编译器不要自作主张:<br>

<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">class Ball { </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;">&nbsp;&nbsp;&nbsp;
explicit&nbsp;Ball(const char*); </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">

<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp; &nbsp;...</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>

<span style="font-weight: bold; font-style: italic;"></span></div>

<span style="font-weight: bold; font-style: italic;"><br>

<br>

</span><br>

</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -