C++ Interfaces in stl::list

2019-07-22 10:07发布

LessonInterface

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

stl container

typedef list<ILesson> TLessonList;

calling code

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

The error:

Description Resource Path Location Type passing ‘const ILesson’ as ‘this’ argument of ‘virtual void ILesson::PrintLessonName()’ discards qualifiers

标签: c++
8条回答
贼婆χ
2楼-- · 2019-07-22 10:32

You have to make PrinLessonName const.

virtual void PrintLessonName() const = 0;

Or not use a const_iterator, of course.

查看更多
Anthone
3楼-- · 2019-07-22 10:32

You want a list of pointers to ILesson's.

IMO, you'd also be considerably better off adding something like:

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

Then, instead of the loop you've written above, you can use something like:

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

As you can see, I've added one other minor embellishment in the process -- PrintLessonName takes a stream as its argument, instead of always printing to the same place. Of course, if you're not using streams, you may not want that...

Edit: Of course the other comments that you want to make PrintLessonPlan const are also correct...

查看更多
Viruses.
4楼-- · 2019-07-22 10:38

You call a non-const method for a const object refered through a reference to const object.

Anyways:

I'm 100% sure you need to have a list of pointers:

typedef list<ILesson*> TLessonList;

in order to take advantage of polymorphism.

Having a list of values of ILesson is not possible, since ILesson is an abstract class.

Don't forget to delete the objects in the list of pointers, to avoid memory leaks.

查看更多
手持菜刀,她持情操
5楼-- · 2019-07-22 10:49

PrintLessonName must be declared as const to be able to be called on const ILessons. Otherwise the compiler assumes it may modify the ILesson and prevents the call.

virtual void PrintLessonName() const = 0;
查看更多
狗以群分
6楼-- · 2019-07-22 10:52

A version like this:

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

lessons.end() gets called once, and also note ++i instead of i++, which is faster (the post-increment operator involves creation of a temporary object, while the pre-increment doesn't).

查看更多
等我变得足够好
7楼-- · 2019-07-22 10:52

People are correct about the lack of const. I'd favour using the for_each algorithm this will prevent calling lessons.end() for every entry.

#include <algorithm> //for for_each()

Then use this:

std::for_each(  lessons.begin(), lessons.end(), std::mem_fun(&ILesson::PrintLessonName) )
查看更多
登录 后发表回答