這段時(shí)間在復(fù)習(xí)C++基礎(chǔ),算法與數(shù)據(jù)結(jié)構(gòu),以及學(xué)習(xí)STL。所以,SDL的教程更新會(huì)慢些。因?yàn)槲疫€是以自己的項(xiàng)目為核心進(jìn)行學(xué)習(xí)的,所以基礎(chǔ)知識(shí)和游戲設(shè)計(jì)涉及到圖形,控制和多線程的內(nèi)容學(xué)習(xí),應(yīng)該是會(huì)有些交叉的。
發(fā)現(xiàn)這個(gè)問(wèn)題,是因?yàn)橐恢币詠?lái)思考的一個(gè)算法——關(guān)于“集合”的實(shí)現(xiàn)。這個(gè)集合就是數(shù)學(xué)中的集合,與計(jì)算機(jī)中數(shù)列一個(gè)最大的不同在于,集合的元素是互異的。因?yàn)檫@兩天在熟悉vector,所以覺(jué)得用vector實(shí)現(xiàn)集合再合適不過(guò)了。STL確實(shí)是很好很強(qiáng)大的體系,無(wú)論是內(nèi)存管理,還是鏈表的實(shí)現(xiàn),讓我們可以省很多心。其實(shí)關(guān)于為什么要實(shí)現(xiàn)集合,也是因?yàn)槲以谟?jì)劃實(shí)現(xiàn)類似英雄無(wú)敵戰(zhàn)場(chǎng)計(jì)算移動(dòng)的一系列算法中,很多地方會(huì)用到集合的概念,甚至包括并集和差集等等。也許我想到的算法是很笨拙的,但是在我還沒(méi)有完全閱讀相關(guān)的已有代碼之前,覺(jué)得完全憑自己的認(rèn)識(shí),實(shí)現(xiàn)這些算法還是很有意義的,所以,從學(xué)習(xí)C++的第一天開(kāi)始,我就在試圖找到解決這些問(wèn)題的方法,而現(xiàn)在,越來(lái)越清晰了,呵呵。
我的思路很直接也很簡(jiǎn)單,就是把一個(gè)數(shù)組中的元素往一個(gè)新的數(shù)組中填,新填充的元素會(huì)遍歷新數(shù)組中已有的元素,如果與之互異,則填入(push),否則就跳到下一個(gè)。以上就已經(jīng)確立了成員數(shù)據(jù)(私有)和構(gòu)造函數(shù)。因?yàn)槲覀冃枰?#8220;集合化”了的數(shù)組是可以被外部訪問(wèn)的,所以一個(gè)最簡(jiǎn)單的方法就是把成員數(shù)據(jù)公有——這確實(shí)是很簡(jiǎn)單,而且這樣就不會(huì)出現(xiàn)今天我們要討論的問(wèn)題了;另外一個(gè)笨辦法是用一個(gè)公有方法,返回成員數(shù)據(jù)的值——我就是這么做的,因?yàn)檫@貌似更符合OOP的“數(shù)據(jù)隱藏”的精神-_-!!!。很快可以寫出頭文件:
#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
請(qǐng)注意那個(gè)紅色的const,其實(shí)我想說(shuō)的是,第一次寫這個(gè)程序的時(shí)候,我并沒(méi)有這個(gè)const。一直以來(lái),除了在重載“=”的時(shí)候我大概清楚修飾返回值const的作用是可以避免讓返回值做左值,其他時(shí)候還真不太明白這個(gè)const的作用,只是本著C++的精神——能const就const吧-_-!!!。實(shí)現(xiàn)文件:
#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;
}
一切都很完美,不是嗎?順手就繼續(xù)寫出一個(gè)測(cè)試用的程序:
#
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;
}
很不幸,編譯正常的通過(guò)了(注意,沒(méi)有紅色的const的時(shí)候)。
但是,運(yùn)行時(shí)出現(xiàn)了錯(cuò)誤。
運(yùn)行時(shí)錯(cuò)誤是件令人很郁悶的事情,因?yàn)檫@意味著編譯器不會(huì)幫你找到出錯(cuò)的地方。
幸運(yùn)的是,直覺(jué)讓我覺(jué)得類似tempAgg.getAgg().begin()的用法有問(wèn)題,所以,我改成了:(紫色那部分代碼)
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);
這樣,問(wèn)題是解決了。但是我們回頭分析一下,剛才的問(wèn)題到底出在什么地方呢?
其實(shí),如果我們加上紅色的const,使用原來(lái)的代碼進(jìn)行編譯的時(shí)候,編譯器是可以指出我們的錯(cuò)誤的,確實(shí)是tempAgg.getAgg().begin()的用法出了問(wèn)題。具體的原因包含在<algorithm>里面,我沒(méi)有仔細(xì)去分析,但是我們至少明白了,方法begin()會(huì)試圖修改其對(duì)象的返回值!
讓錯(cuò)誤被發(fā)現(xiàn)在編譯階段,遠(yuǎn)遠(yuǎn)好于被發(fā)現(xiàn)在運(yùn)行時(shí)階段。我想,這就是C++中const最大的作用。所以,總結(jié)起來(lái)還是C++的一句話,能const,就const吧。:)