如何将链表转换为C ++向量(为什么这段代码不起作用?)

时间:2017-04-24 19:35:36

标签: c++ stl

我有一些遗留代码,它使用显式链接列表来保存定期循环的事件列表。而不是定义下一个'在每个事件节点中的指针,我认为矢量会更紧凑&然而,更有效率的转换我认为是直截了当的,让我进入圈内。我将问题减少到1个文件和一个较小的代码子集,它使用条件' #define'编译LL版本或矢量版本。在LL版本编译时,我无法获得 看起来 的STL版本,就像它应该是等效的,以便干净地编译。

这是测试代码:

#define dummy_defs
//#define USE_LL

#ifndef USE_LL
#include <vector>
using std::vector;
#endif

#ifdef dummy_defs
#define QueuedAfterReading 1
typedef union _XEvent { int type; } XEvent;
void XNextEvent(void) {}
int XEventsQueued(void) {}
#endif


class XWin;

typedef void (XWin::*EventCallBack) (XEvent &event);

class XWin {

    static XWin * xparent;

protected:

    class Event {
        EventCallBack callBack_{};
        int event_{};
#ifdef USE_LL
        Event * next{};
#endif
    public:
        friend XWin;
        Event(int event, EventCallBack callBack);
        virtual ~Event(void){}

        void callBack(XEvent &x_event) {
            if (x_event.type == event_) (xparent->*callBack_)(x_event);
        }
    };

#ifdef USE_LL
    Event * events_{};
#else
    vector<Event *> events_{};
#endif

    inline void add_event(int event, EventCallBack callBack) {
#ifdef USE_LL
        Event * tmp;
        if (events_ == nullptr) events_ = new Event(event, callBack);
        else {
            tmp=events_;
            while (tmp->next) tmp=tmp->next;
            tmp->next=new Event(event, callBack);
        }
#else
        events_.emplace_back(new Event(event, callBack));
#endif
    }

    void checkevent(void);
};

XWin * XWin::xparent=nullptr;

void XWin::checkevent(void) {
    XEvent x_event;

    while (XEventsQueued()) {
        XNextEvent();

#ifdef USE_LL
        for (Event * tmp=events_; tmp; tmp=tmp->next)
            tmp->callBack(x_event);
#else
        for (Event * tmp:events_) (tmp->callBack)(x_event);
#endif
    }
}

上面(在C ++ 11中)给出了错误:

test.cc: In member function ‘void XWin::checkevent()’:
test.cc:79:53: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘tmp->XWin::Event::callBack_ (...)’, e.g. ‘(... ->* tmp->XWin::Event::callBack_) (...)’
   for (Event * tmp:events_) (tmp->callBack_)(x_event);
                                                 ^

如果我尝试按照错误&#34;&#34;说明&#34;,并添加&#39; *&#39;, 我明白了:

test.cc: In member function ‘void XWin::checkevent()’:
test.cc:79:36: error: ‘callBack_’ was not declared in this scope
   for (Event * tmp:events_) (tmp->*callBack)(x_event);
                                    ^~~~~~~~~

即。 - 另一个错误。第一种形式&#34; tmp-&gt; callBack _&#34;似乎与USE_LL案件相似并且考虑到了&#39; tmp&#39;声明属于&#39;事件*&#39;,我认为访问&#39;事件&#39;中的成员将具有相同的形式,但编译器不会抱怨

程序创建一个在创建后未被修改的事件列表,因此通过STL向量的基本&#39; -type容器似乎是最有效的实现。有人可以指出为什么这两个实现不等同,以及我应该如何制作它们(没有&#39;治愈比原来更糟糕)?

谢谢, -Astara

P.S。修复了矢量大小写以调用代理函数&#39;回调&#39; (有 打回来_)。我试过了,但在某个地方它被修改了。我给出了这个错误:

test.cc: In member function ‘void XWin::checkevent()’:
test.cc:79:36: error: ‘callBack’ was not declared in this scope
   for (Event * tmp:events_) (tmp->*callBack)(x_event);
                                    ^~~~~~~~

2 个答案:

答案 0 :(得分:0)

为了清楚起见,@ user4581301的评论有助于解决原因设计过度使用类似拼写的名称(例如event v.vent_&amp;)所引起的语义问题。具有一些拼写的事件被用于多种类型。当我去校对时,多种变化使得很难看到错误,而且用户4581301指出这些足以让我解决问题。这种混淆是我试图“重构”代码的一个原因。如果有人想看到更正的版本,我会在这里发布。

#define dummy_defs

/*
* The above question demonstrated the original code's use
* of a linked-list that one could 'test' by defining 'USE_LL'.
* The C++ STL implementation uses vector.  For clarity, I'll
* leave out the old LL code.
*/

#include <vector>
using std::vector;

// dummy defs to satisfy dependencies similarly to original code
#ifdef dummy_defs
typedef union _XEvent { int type; } XEvent;
void XNextEvent(void) {}
int XEventsQueued(void) {}
#endif


class XWin;

typedef void (XWin::*EventCallBack) (XEvent &event);

class XWin {

  static XWin * xparent;

protected:

  class Event {
    EventCallBack callBack_{};
    int event_{};
  public:
    friend XWin;
    Event(int event, EventCallBack callBack);
    virtual ~Event(void){}

    void callBack(XEvent &x_event) {
      if (x_event.type == event_) (xparent->*callBack_)(x_event);
    }
  };

  vector<Event *> events_{};

  inline void add_event(int event, EventCallBack callBack) { 
    events_.emplace_back(new Event(event, callBack));
  }

  void checkevent(void);
};

XWin * XWin::xparent=nullptr;

void XWin::checkevent(void) {
  XEvent x_event;

  while (XEventsQueued()) {
    XNextEvent();
    for (auto tmp:events_) tmp->callBack(x_event);
  }
}

答案 1 :(得分:-2)

    Your code commented by me:

    #define dummy_defs
    //#define USE_LL
    #ifndef USE_LL
    #include <vector>  //object library type (might or not be an issue)
    using std::vector; // 'std' means 'provided' here
    #endif

    #ifdef dummy_defs
    #define QueuedAfterReading 1
    //your type definition
    typedef union _XEvent { 
    int type; 
    } 
    XEvent; 
    void XNextEvent(void) {
    }
    int XEventsQueued(void) {
    }
    #endif

    class XWin;
    //'asterisk' means you are using an 'address' for the value, not the value itself
    typedef void (XWin::*EventCallBack) (XEvent &event);
    //Your XWin class
    class XWin {

        static XWin * xparent;//'asterisk' means you are using an 'address' for the parent's value, not the value itself

    protected: //scope for the class below

        class Event {
            EventCallBack callBack_{
            };
            int event_{};
    #ifdef USE_LL
            Event * next{};//address of next() node, not the node itself
    #endif
        public: //scope for the block below
            friend XWin;
            Event(int event, EventCallBack callBack);//this function arguments are not the same as above, the underscore makes a difference
            virtual ~Event(void){}

            void callBack(XEvent &x_event) {
                if (x_event.type == event_) (xparent->*callBack_)(x_event);
            }
        };

    #ifdef USE_LL
        Event * events_{};
    #else
        vector<Event *> events_{};
    #endif

        inline void add_event(int event, EventCallBack callBack) {
    #ifdef USE_LL
            Event * tmp;
            if (events_ == nullptr) events_ = new Event(event, callBack);
            else {
                tmp=events_;
                while (tmp->next) tmp=tmp->next;
                tmp->next=new Event(event, callBack);
            }
    #else
            events_.emplace_back(new Event(event, callBack));
    #endif
        }

        void checkevent(void);
    };

    XWin * XWin::xparent=nullptr;

    void XWin::checkevent(void) {
        XEvent x_event;

        while (XEventsQueued()) {
            XNextEvent();

    #ifdef USE_LL
            for (Event * tmp=events_; tmp; tmp=tmp->next)
                tmp->callBack(x_event);
    #else
            for (Event * tmp:events_) (tmp->callBack)(x_event);
    #endif
        }
    }
    //Block with 'public:' scope and the related function into the class 'Event' whose scope is 'protected:' <--- , declared above
    (I think the PROBLEM IS HERE, check it and tell me).
    public: // <--- scope for the block below
            friend XWin;
            Event(int event, EventCallBack callBack);//this function arguments are not the same as above, the underscore makes a difference
            virtual ~Event(void){}

            void callBack(XEvent &x_event) {
                if (x_event.type == event_) (xparent->*callBack_)(x_event);
            }
        };

    The compiler error message before dereferencing:

        test.cc:79:53: error: must use ‘.*’ or ‘->*’ <--- dereference needed ---> :) to call pointer-to-member function in ‘tmp->XWin::Event::callBack_ (...)’, e.g. ‘(... ->* tmp->XWin::Event::callBack_) (...)’
           for (Event * tmp:events_) (tmp->callBack_)(x_event);

    The compiler error message after dereferencing:

        test.cc: In member function ‘void XWin::checkevent()’:
        test.cc:79:36: error: ‘callBack_’ was not declared in this scope <--- 'scope' ---> :)
           for (Event * tmp:events_) (tmp->*callBack)(x_event);