【问题标题】:C++ Interfaces in stl::liststl::list 中的 C++ 接口
【发布时间】:2009-10-21 15:05:35
【问题描述】:

课程界面

class ILesson
{
    public:
        virtual void PrintLessonName() = 0;
        virtual ~ILesson() {}
};

stl 容器

typedef list<ILesson> TLessonList;

调用代码

for (TLessonList::const_iterator i = lessons.begin(); i != lessons.end(); i++)
    {
        i->PrintLessonName();
    }

错误:

描述资源路径位置类型 将“const ILesson”作为“this”传递 论“虚空” ILesson::PrintLessonName()' 丢弃 限定词

【问题讨论】:

    标签: c++


    【解决方案1】:

    PrintLessonName 必须声明为 const 才能在 const ILessons 上调用。否则编译器会假定它可能会修改 ILesson 并阻止调用。

    virtual void PrintLessonName() const = 0;
    

    【讨论】:

      【解决方案2】:

      您不能“放置”具有纯虚函数的类的对象(因为您不能实例化它)。也许你的意思是:

      // store a pointer which points to a child actually.
      typedef list<ILesson*> TLessonList;
      

      好的,正如其他人指出的那样,您必须将 PrintLessonName 设为 const 成员函数。我要补充一点,这里还有一个小陷阱。 PrintLessonNamebasederived 类中必须是 const,否则它们将具有相同的签名:

      class ILesson
      {
      public:
          virtual void PrintLessonName() const = 0;
          virtual ~ILesson() {}
      };
      
      
      class SomeLesson : public ILesson
      {
      public:
          // const is mandatory in the child
          virtual void PrintLessonName() const
          {
              //
          }
          virtual ~SomeLesson() {}
      };
      

      说实话,我发现Jerry Coffin's 的回答有助于重新设计打印功能。

      【讨论】:

      • 虽然这是真的,但杰克粘贴的错误消息不是由于此错误。
      • 尝试过并且错误是:描述资源路径位置类型请求成员 'PrintLessonName' in '* i.std::_List_const_iterator<_tp>::operator-> [with _Tp = ILesson*]() ',属于非类类型'ILesson* const'
      • 我没有观察到 const 问题,我的目光首先落在了typedef list&lt;ILesson&gt; TLessonList;。无论如何,他也必须解决这个问题。
      • @jack:改用(*i)-&gt;PrintLessonName()。由于您现在使用的是指针,因此取消引用迭代器会产生一个指针而不是一个对象实例。
      【解决方案3】:

      您必须将 PrinLessonName 设为 const。

      virtual void PrintLessonName() const = 0;
      

      当然也可以不使用 const_iterator。

      【讨论】:

        【解决方案4】:

        你想要一个指向 ILesson 的指针列表。

        IMO,您最好添加以下内容:

        std::ostream &operator<<(std::ostream &os, ILesson const *il) { 
            il->PrintLessonName(os);
            return os;
        }
        

        然后,您可以使用以下内容,而不是上面编写的循环:

        std::copy(lessons.begin(), lessons.end(), 
                  std::ostream_iterator<ILesson *>(std::cout));
        

        如您所见,我在此过程中添加了另一个小装饰—— PrintLessonName 将流作为其参数,而不是总是打印到同一个地方。当然,如果你不使用流,你可能不希望这样......

        编辑:当然,您要使 PrintLessonPlan const 的其他 cmets 也是正确的...

        【讨论】:

          【解决方案5】:

          使用iterator 代替const_iterator 或制作PrintLessonName() const 函数:

          virtual void PrintLessonName() const = 0
          

          【讨论】:

          • 呃。改为使用const 函数怎么样?我们并不希望打印会改变打印的对象。
          • 阅读我的答案“或使函数 CONST”
          • 啊,我的大脑像 AraK 一样工作。阅读删除 const 的建议并拒绝投票。对不起。我将删除我的反对票(但只要您建议删除 const,我就不会赞成)。
          • @sbi 这些是 SO 加班综合症;)
          • @sbi 如果我想在 PrintLessonName() 中增加一个计数器,该计数器将计算完成的打印次数。同意不是世界上最好的代码,但可能。同样作为一个经验法则,不要将 const 放在虚拟方法上,因为您不知道有人将如何使用它们。
          【解决方案6】:

          您为通过对 const 对象的引用引用的 const 对象调用非 const 方法。

          无论如何:

          我 100% 确定您需要一个指针列表:

          typedef list<ILesson*> TLessonList;
          

          为了利用多态性。

          拥有ILesson 的值列表是不可能的,因为ILesson 是一个抽象类。

          不要忘记删除指针列表中的对象,以避免内存泄漏。

          【讨论】:

            【解决方案7】:

            这样的版本:

            for (TLessonList::const_iterator i=lessons.begin(), m=lessons.end();  i!=m;  ++i)
                {
                    i->PrintLessonName();
                }
            

            lessons.end() 被调用一次,并且注意 ++i 而不是 i++,它更快(后增量运算符涉及创建临时对象,而前增量不涉及)。

            【讨论】:

              【解决方案8】:

              人们对缺少 const 的看法是正确的。 我倾向于使用 for_each 算法,这将防止为每个条目调用课程.end()。

              #include <algorithm> //for for_each()
              

              然后使用这个:

              std::for_each(  lessons.begin(), lessons.end(), std::mem_fun(&ILesson::PrintLessonName) )
              

              【讨论】:

                猜你喜欢
                • 2014-08-13
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-10-15
                • 2012-05-09
                • 1970-01-01
                相关资源
                最近更新 更多