提倡同學們積累代碼行數,于是有了大量的編程練習。做下來是一個基本的要求,對個別同學而言,已經是輕松面對,他們在基本編程能力方面,已經有了保障,這為今后的學習和自學打下了好的基礎。一些同學一路緊隨,跟住了都不是易事,有些依然不能按時按量完成。心中想著要多做幾個,但調試中遇到問題,難免急躁。
看到一位同學在博文最后寫的一段話:“直接抓狂了,經過個人分析,應該是函數change24與changefrom0沒有實現其功能,可是定義函數,函數的賦值及調用都與其他同學的相同,問題究竟出在哪里啊?求指點!”
這是C++第7周項目1 - 靜態成員應用于時間類(見[http://blog.csdn.net/sxhelijian/article/details/8795951](http://blog.csdn.net/sxhelijian/article/details/8795951)) 的題目。目標是學會靜態數據成員以及靜態成員函數的用法。
下面是只涉及靜態數據成員以及靜態成員函數的用法的“縮略版”解答,當然,包含這位同學犯的錯誤。請讀者先讀完這段程序。
~~~
#include <iostream>
#include<string>
using namespace std;
class Time
{
public:
Time(int=0,int=0,int=0);
void show_time( ); //根據is_24和from0,輸出適合形式-20:23:5/8:23:5 pm/08:23:05 pm
static void change24(); //改變靜態成員is_24,在12和24時制之間轉換
static void changefrom0(); //改變靜態成員from0,切換是否前導0
private:
static bool is_24; //為true時,24小時制,如20:23:5;為flase,12小時制,顯示為8:23:5 pm
static bool from0; //為true時,前導0,8:23:5顯示為08:23:05
int hour;
int minute;
int sec;
};
Time::Time(int h,int m,int s)
{
hour=h;
minute=m;
sec=s;
}
bool Time::is_24=true;
bool Time::from0=false;
void Time::show_time( )
{
int h=(is_24)?hour:hour%12;
if (h<10&&from0) cout<<'0';
cout<<h<<':';
if(minute<10&&from0) cout<<'0';
cout<<minute<<':';
if(sec<10&&from0) cout<<'0';
cout<<sec;
if(!is_24)
cout<<((hour>12)? " pm":" am");
cout<<endl;
}
void Time::change24()
{
is_24=!is_24;
}
void Time::changefrom0()
{
from0=!from0;
}
int main( )
{
Time t1(23,14,25),t2(8,45,6);
cout<<"24小時制,不導0:"<<endl;
t1.show_time();
t2.show_time();
cout<<"切換是否前導0:"<<endl;
t1.changefrom0();
t2.changefrom0();
t1.show_time();
t2.show_time();
cout<<"換一種制式:"<<endl;
t1.change24();
t2.change24();
t1.show_time();
t2.show_time();
}
~~~
這段程序的實際運行結果是:

可以發現,切換是否前導0,換制式,根本沒有起作用。預期中的結果應該是:

面對運行中的問題,最直接的辦法就是采用單步執行的辦法,跟蹤一下程序在執行過程中,相關變量的變化過程。顯然,這位同學并沒有這樣做過。
一再強調的調程序的“利器”,就被藏在“兵器庫”中,任由其閑置。這種技能就是要在實踐中學會的,這是學會的最佳時刻。有些同學已經用得純熟,有些還在躲避。同一個教室上課,差別怎么這么大。
不說這些了。其實,不用單步調試,這個事不好做,也真不好說。初學有關知識,都要靠著推理式的排查,這是更難的辦法。
這個程序中包括main()函數在內一共5個函數。類的構造函數Time()和用于顯示的函數Time::show_time()嫌疑不大,先放過。main()似乎中規中矩,也放下。Time::changefrom0()和Time::change24()與以前編程的程序中有點不一樣,聲明前加了個static,這時可以看書了,明確這叫做靜態成員函數,靜態成員函數是用來使用靜態數據成員的,再看static bool is_24; 和static bool from0; ,這兩個成員不一般,靜態的,靜態的有何特點?它不屬于任何一個對象,屬于類。然后看看講義,老師講過這個圖:

圍繞著“靜態”,找到main()函數中有這么兩句,調用的是靜態成員函數:
~~~
t1.changefrom0();
t2.changefrom0();
~~~
這兩個靜態成員函數操作的將是同一個數據Time::from0,盡管t1.changefrom0()和t2.changefrom0()前面打著t1、t2人民的旗號,干得都是服務大眾的工作。from0和hour等不一樣,它是靜態的。
于是明白了吧。t1.changefrom0()將from0由假為真,t2.changefrom0()又將from0由真為假,最后輸出沒有變化。
發生在is_24上的事情也是一樣。
程序運行結果不在預期中,這是學習的最佳機會。
稀里糊涂走進來,明明白白走出去。這大概是積累代碼行的路線中應該收獲的,而其中需要的,是冷靜,以及實踐與看書的結合。
最后,還說,單步調試,閑著太可惜。