Chinaunix首页 | 论坛 | 博客
  • 博客访问: 415439
  • 博文数量: 116
  • 博客积分: 7087
  • 博客等级: 少将
  • 技术积分: 1175
  • 用 户 组: 普通用户
  • 注册时间: 2005-02-19 23:32
文章分类

全部博文(116)

文章存档

2012年(1)

2011年(2)

2010年(10)

2009年(21)

2008年(18)

2007年(12)

2006年(21)

2005年(31)

我的朋友

分类:

2005-04-15 15:38:36

使用stl的时候,如果发现编译出错,解读出错信息,对程序员来说,的确是个很大的考验。因为,错误隐藏在复杂的描述信息中。

使用stl开发程序,出错是难免的。如何有效的发现错误,然后纠正,才是关键。但是stl的出错信息实在是不高明,复杂的模版扩展开来之后,一看就头晕。下面举个例子,不是教人怎么看,只是就事论事。

先看程序:

wostream & operator<< (wostream &out, const table &t)
{
 typedef list  lr;
 typedef lr::const_iterator rowi;
 rowi ir;
 ir=t.c.begin();                                //<-------------编译会出错.
 table p(t); 
 ir=p.c.begin();
 cout<<"table t:"< cout<<"table:"< out<<*ir< return out;
}

如果这么写,编译出错信息是:

Error 226: "table.cpp", line 49 # No appropriate function found for call of
    'operator ='. Last viable candidate was "std::__rw_list_iter    *,row &> &std::__rw_list_iter::operator =(const
    std::__rw_list_iter &)"
    ["/opt/aCC/include_std/list", line 72]. Argument of type 'class
    __rw_list_iter' could not be converted
    to 'const std::__rw_list_iter &'.
            ir=t.c.begin();
            ^^^^^^^^^^^^^^
*** 错误退出代码 2
一开始,这段提示完全看不懂,根本不知道什么错.虽然全是英语,但是无法理解.之后尝试了很多方法,比如说再建立一个table变量,由它复制参数t,然后由这个中间变量取出iterator。

很明显,这样的做法,开销太大。我相信,stl里肯定有简单的解决方案,只是我还不知道。

上论坛,看书,兜了一大圈,终于开了壳。当然灵感还是来自于错误提示。

Argument of type 'class   __rw_list_iter' could not be converted
                   to 'const std::__rw_list_iter< row,long,          row *,         row &> &'.

上面这句话很关键,意思就是说两个对象,数据类型不一样,无法转换。而且是前者无法转为后者。前者里面有const,很明显是我传入的参数。因为不希望传入的参数被改动,因此用了const来限定它。

后面的肯定是我在函数体中定义的iterator,这是个普通的iterator,可以修改对象的。两个产生了矛盾,问题应该出在这里。

解决的方法似乎很简单,把传入参数的const去掉即可。

于是我试了试,编译还是出错。这次我没细看,以为还是不行,于是继续研究。

经过一天的时间,晚上和白天都在思考这个问题,终于能够把我看到的一鳞半爪的知识连贯起来想想了。如果const 不能去掉,我应该可以用const iterator来接受参数t中的iterator啊。实际上,我也是今天白天才看到有const_iterator这么一个东西。

于是修改函数为下面形式:

wostream & operator<< (wostream &out, const table &t)
{
 typedef list  lr;
 typedef lr::const_iterator rowi;
 rowi ir;
 ir=t.c.begin();
 cout<<"table t:"< out<<*ir< return out;
}

这样处理很快就搞定了。 :-)  果然很简单,但是没人告诉你,你就是不知道。

在写这篇帖子的时候,自己的思路也慢慢清晰起来。回头再看看当时的想法,去掉参数中的const限制符,应该也行。不行反而是没有道理的。于是,动手修改程序,再试。

wostream & operator<< (wostream &out, table &t)
{
    typedef list  lr;
    typedef lr::iterator rowi;
    rowi ir;
    ir=t.c.begin();
    cout<<"table t:"<    out<<*ir<    return out;
}


还是出错,但是看错误提示,问题好象出在我的测试程序中。

ld: Unsatisfied symbol "operator <<(std::basic_ostreamwchar_t>> &,const table &)" in file test.o
1 errors.

仔细看看这里的提示,发现test.o里面对于重载的操作符的格式还是老样子,居然没有变化。想想原因,估计是以前编译好的信息存放在test.o中。因为test.cpp文件一直没有变过,而我又是用make来做,所以test.o也没有更新。那么删除test.o,重新编译一下吧。

这次果然也成功了。两种方法,效果是一样的。当然从安全性来考虑,用const_iterator会更安全一些。

经过这次的学习,对stl的理解更加深刻了。

阅读(1747) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-05-09 17:47:11

确实不错。 虽然不是用C++开发的, 也学习了。