这段时间在复习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 阅读(911)
评论(3) 编辑 收藏 引用 所属分类:
语言基础、数据结构与算法