http://www./lf426/archive/2008/03/13/44360.html 2008.03
这段时间在复习C++基础,算法与数据结构,以及学习STL。所以,SDL的教程更新会慢些。因为我还是以自己的项目为核心进行学习的,所以基础知识和游戏设计涉及到图形,控制和多线程的内容学习,应该是会有些交叉的。发现这个问题,是因为一直以来思考的一个算法——关于“集合”的实现。这个集合就是数学中的集合,与计算机中数列一个最大的不同在于,集合的元素是互异的。因为这两天在熟悉vector,所以觉得用vector实现集合再合适不过了。STL确实是很好很强大的体系,无论是内存管理,还是链表的实现,让我们可以省很多心。其实关于为什么要实现集合,也是因为我在计划实现类似英雄无敌战场计算移动的一系列算法中,很多地方会用到集合的概念,甚至包括并集和差集等等。也许我想到的算法是很笨拙的,但是在我还没有完全阅读相关的已有代码之前,觉得完全凭自己的认识,实现这些算法还是很有意义的,所以,从学习C++的第一天开始,我就在试图找到解决这些问题的方法,而现在,越来越清晰了,呵呵。 我的思路很直接也很简单,就是把一个数组中的元素往一个新的数组中填,新填充的元素会遍历新数组中已有的元素,如果与之互异,则填入(push),否则就跳到下一个。以上就已经确立了成员数据(私有)和构造函数。因为我们需要“集合化”了的数组是可以被外部访问的,所以一个最简单的方法就是把成员数据公有——这确实是很简单,而且这样就不会出现今天我们要讨论的问题了;另外一个笨办法是用一个公有方法,返回成员数据的值——我就是这么做的,因为这貌似更符合OOP的“数据隐藏”的精神-_-!!!。很快可以写出头文件: #ifndef AGGREGATE_H_
请注意那个红色的const,其实我想说的是,第一次写这个程序的时候,我并没有这个const。一直以来,除了在重载“=”的时候我大概清楚修饰返回值const的作用是可以避免让返回值做左值,其他时候还真不太明白这个const的作用,只是本着C++的精神——能const就const吧-_-!!!。实现文件:#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 #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"
很不幸,编译正常的通过了(注意,没有红色的const的时候)。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; } 但是,运行时出现了错误。 运行时错误是件令人很郁闷的事情,因为这意味着编译器不会帮你找到出错的地方。 幸运的是,直觉让我觉得类似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吧。:) |
|
来自: 心不留意外尘 > 《ccpp for hardware》