這段時間在復習C++基礎,算法與數據結構,以及學習STL。所以,SDL的教程更新會慢些。因為我還是以自己的項目為核心進行學習的,所以基礎知識和游戲設計涉及到圖形,控制和多線程的內容學習,應該是會有些交叉的。
發現這個問題,是因為一直以來思考的一個算法——關于“集合”的實現。這個集合就是數學中的集合,與計算機中數列一個最大的不同在于,集合的元素是互異的。因為這兩天在熟悉vector,所以覺得用vector實現集合再合適不過了。STL確實是很好很強大的體系,無論是內存管理,還是鏈表的實現,讓我們可以省很多心。其實關于為什么要實現集合,也是因為我在計劃實現類似英雄無敵戰場計算移動的一系列算法中,很多地方會用到集合的概念,甚至包括并集和差集等等。也許我想到的算法是很笨拙的,但是在我還沒有完全閱讀相關的已有代碼之前,覺得完全憑自己的認識,實現這些算法還是很有意義的,所以,從學習C++的第一天開始,我就在試圖找到解決這些問題的方法,而現在,越來越清晰了,呵呵。
我的思路很直接也很簡單,就是把一個數組中的元素往一個新的數組中填,新填充的元素會遍歷新數組中已有的元素,如果與之互異,則填入(push),否則就跳到下一個。以上就已經確立了成員數據(私有)和構造函數。因為我們需要“集合化”了的數組是可以被外部訪問的,所以一個最簡單的方法就是把成員數據公有——這確實是很簡單,而且這樣就不會出現今天我們要討論的問題了;另外一個笨辦法是用一個公有方法,返回成員數據的值——我就是這么做的,因為這貌似更符合OOP的“數據隱藏”的精神-_-!!!。很快可以寫出頭文件:
#ifndef AGGREGATE_H_
#define AGGREGATE_H_
#include <iostream>
#include <vector>
#include <algorithm>
class Aggregate
{
private:
std::vector<int> agg;
public:
Aggregate(std::vector<int>& temp);
const std::vector<int> getAgg() const;
};
#endif
請注意那個紅色的const,其實我想說的是,第一次寫這個程序的時候,我并沒有這個const。一直以來,除了在重載“=”的時候我大概清楚修飾返回值const的作用是可以避免讓返回值做左值,其他時候還真不太明白這個const的作用,只是本著C++的精神——能const就const吧-_-!!!。實現文件:
#include "aggregate.h"
Aggregate::Aggregate(std::vector<int>& temp)
{
for ( std::vector<int>::iterator pTemp = temp.begin(); pTemp != temp.end(); pTemp++ ) {
bool findSame = false;
for ( std::vector<int>::iterator pAgg = agg.begin(); pAgg != agg.end(); pAgg++ )
if ( *pTemp == *pAgg )
findSame = true;
if ( findSame == false )
agg.push_back(*pTemp);
}
}
const std::vector<int> Aggregate::getAgg() const
{
return agg;
}
一切都很完美,不是嗎?順手就繼續寫出一個測試用的程序:
#
include "aggregate.h"
void show(
int& i);
int main(
int argc,
char* argv[])
{
std::vector<
int> tempArray;
int temp;
bool goon =
true;
while ( goon ==
true ) {
std::cout << "#" << tempArray.size()+1 << "= ";
std::cin >> temp;
if ( temp == -1 ) {
goon =
false;
continue;
}
tempArray.push_back(temp);
}
std::cout << "You've entered " << tempArray.size() << " numbers." << std::endl;
for_each(tempArray.begin(), tempArray.end(), show);
std::cout << "----------------------------\n" << "Now, to be aggregate
\n";
Aggregate tempAgg (tempArray);
std::cout << "There are " << tempAgg.getAgg().size() << " different numbers.\n";
for_each(tempAgg.getAgg().begin(), tempAgg.getAgg().end(), show); return 0;
}
void show(
int& i)
{
std::cout << i << std::endl;
}
很不幸,編譯正常的通過了(注意,沒有紅色的const的時候)。
但是,運行時出現了錯誤。
運行時錯誤是件令人很郁悶的事情,因為這意味著編譯器不會幫你找到出錯的地方。
幸運的是,直覺讓我覺得類似tempAgg.getAgg().begin()的用法有問題,所以,我改成了:(紫色那部分代碼)
std::cout << "----------------------------\n" << "Now, to be aggregate
\n";
Aggregate tempAgg (tempArray);
std::vector<int> tempAggArray = tempAgg.getAgg();
std::cout << "There are " << tempAggArray.size() << " different numbers.\n";
for_each(tempAggArray.begin(), tempAggArray.end(), show);
這樣,問題是解決了。但是我們回頭分析一下,剛才的問題到底出在什么地方呢?
其實,如果我們加上紅色的const,使用原來的代碼進行編譯的時候,編譯器是可以指出我們的錯誤的,確實是tempAgg.getAgg().begin()的用法出了問題。具體的原因包含在<algorithm>里面,我沒有仔細去分析,但是我們至少明白了,方法begin()會試圖修改其對象的返回值!
讓錯誤被發現在編譯階段,遠遠好于被發現在運行時階段。我想,這就是C++中const最大的作用。所以,總結起來還是C++的一句話,能const,就const吧。:)
posted on 2008-03-13 13:30
lf426 閱讀(931)
評論(3) 編輯 收藏 引用 所屬分類:
語言基礎、數據結構與算法