【问题标题】:Error in assignment of member in read-only object只读对象中的成员分配错误
【发布时间】:2012-08-28 04:44:15
【问题描述】:

我正在研究 worm_sim 模拟器、ubuntu、gcc、codeblocks IDE

traffic_source.h 文件

class Traffic_source : public Buffer_owner, public Connector, public Addressee{
private:
    static unsigned int id_base;
    unsigned int id;
    unsigned int packet_size;
    unsigned int flit_size;
    double packet_generating_rate;
    int pkt_id;
    traffic_source_state ts_state;
    double* packet_to_destination_rate;
    Traffic_mode traffic_mode;
    int period;                // period for packet generation using trace_file
    ifstream trace_file;
    int trace_file_loop_cnt;   // how many times we have gone over the trace file so far
    bool trace_file_empty;
    ofstream trace_dump;       // trace file to dump out

    typedef struct Message {
        int timestamp;
        unsigned int destination;
        unsigned int size;
    } Message, *pMessage;

    Message pre_fetched_message;
    bool get_next_message(Message & msg);

    unsigned int get_destination_uniform(void) const; 
    unsigned int get_destination_transpose1(void) const;
    unsigned int get_destination_transpose2(void) const;
    unsigned int get_destination_hotspot(void) const;
    unsigned int get_destination_customized(void) const;

    void generate_a_packet(unsigned int dst_id);
    void generate_packets(const Message & rec);

public:
    Traffic_source(Position p, int buf_sz);
    ~Traffic_source();
    bool can_send(void) const;
    bool can_receive(void) const { return false; }
    bool send(void);
    bool receive(class Flit * a_flit) { return false; }
    class Connector * get_receiver(void) const; 

    static void reset_id_base(void) { id_base = 0; }

    void tick(void);

    /* traffic control routines */
    void set_packet_generating_rate(double r);
    void set_packet_to_destination_rate(unsigned int dst_id, double rate);
    double get_packet_to_destination_rate(unsigned int dst_id) const;
    double get_total_packet_injection_rate(void) const;
    int set_trace_file(char * file_name);
    bool has_trace_file(void) { return (trace_file.is_open()); }
    int get_id(void) const { return id; }
};

traffic_source.cpp

Traffic_source::Traffic_source(Position p, int buf_sz) : Buffer_owner(buf_sz), Addressee(p) {
    id = id_base ++;
    packet_generating_rate = param.packet_generating_rate;
    packet_size = param.flits_per_packet;
    flit_size = param.flit_size;
    traffic_mode = param.traffic_mode;
    period = 0;
    packet_to_destination_rate = 0;
    pkt_id = 0;
    ts_state = OFF_

    if (param.dump_traffic_source_trace) {
        char file_name[20];
        sprintf(file_name, "%d.trace", id);
        trace_dump.open(file_name);
        if (!trace_dump.is_open() || !trace_dump.good()) {
            cerr << "Error in opening file " << file_name << " for trace dumping" << endl;
            exit(-1);
        }
        trace_dump << "PERIOD\t" << param.simulation_length << endl;
        trace_dump << "#Trace file dumped by worm_sim from node " << id << endl;
        trace_dump << "#Folloing lines are with format as:" << endl
                   << "#timestamp\t" << "destination\t" << "message_size(bits):" << endl;
    }
}

bool Traffic_source::can_send(void) const
{
    int router_id=get_id();
    unsigned int local_availability;

    pRouter a_router= param.network->get_router(router_id);
    local_availability=a_router->get_port_availability(0);
    //cout<<local_availability<<endl;
    if (buffer.is_empty())
        return false;
    if(local_availability <= 0)
    {
        packet_generating_rate = 0; //error: assignment of member ‘Traffic_source::packet_generating_rate’ in read-only object|
        set_packet_generating_rate(0); // error: passing ‘const Traffic_source’ as ‘this’ argument of ‘void Traffic_source::set_packet_generating_rate(double)’ discards qualifiers [-fpermissive]|
        return false;
    }


    // This is somehow trick, we need to verify whether the first flit in the fifo
    // is received right in this clock cycle. If so, we can not send it
    const Flit * first_flit = buffer.peek_flit();
    if (first_flit->arrived_in_this_cycle())
        return false;

    pConnector receiver = get_receiver();

    if (receiver)
        return receiver->can_receive();
    else
        return false;
}

packet_generating_rate 的值不是 const,但是当我尝试直接修改它或使用 set 函数时,它会给我错误

packet_generating_rate = 0; //error: assignment of member    
 ‘Traffic_source::packet_generating_rate’ in read-only object|

set_packet_generating_rate(0); // error: passing ‘const Traffic_source’ as ‘this’ argument of ‘void Traffic_source::set_packet_generating_rate(double)’ discards qualifiers [-fpermissive]|

虽然它用在其他文件上没有问题,任何建议plz

【问题讨论】:

    标签: c++ compiler-errors variable-assignment


    【解决方案1】:
    bool Traffic_source::can_send(void) const
    

    正如其他人已经指出的那样,问题是在const 函数内部(最后一个const 在行中)您不能修改对象的成员。实际上,成员函数被翻译成类似于:bool Traffic_source__can_send( const Traffic_source* this, void )this 参数是指向const 的指针。这反过来意味着packet_generating_rate const 在函数的上下文中。

    您可以在此处遵循三种选择:

    • 不要修改成员
    • 不要标记函数const
    • 制作packet_generating_ratemutable

    前两个选项是常见的:要么函数是const,不修改对象,要么不是const,可以修改对象。但是,在某些情况下,您想要修改const 成员指针中的成员。在这种情况下,您可以将成员声明标记为 mutable 以在 const 成员函数中启用修改。

    但是请注意,通常这是在成员变量不参与对象的 可见 状态时完成的。例如,mutex 变量不会改变 getter 返回的值或之后对象的状态,但 getter 需要锁定(修改)对象以获得在多线程环境中对象的一致视图。第二个典型示例是缓存,其中一个对象可能提供计算成本高昂的操作,因此执行该操作的函数可能缓存结果以备后用。同样,无论是重新计算值还是从 缓存 中检索该值都是相同的,因此对象的可见状态不会改变。最后,有时您可能需要滥用该构造以符合现有接口。

    现在由您决定将三个选项中的哪一个应用于您的设计。如果需要修改成员属性,那么要么成员是可见状态的一部分,函数不应该是const,要么它不是对象状态的一部分,可以标记为mutable

    【讨论】:

      【解决方案2】:
      packet_generating_rate = 0;
      

      在常量函数内部使用。在常量函数中,您不能更改调用该函数的对象的任何数据成员的值。

      【讨论】:

        【解决方案3】:
        bool Traffic_source::can_send(void) const
        

        此声明将this 转换为指向const 的指针。将方法标记为 const 会使实例不可变,因此您无法修改其成员。

        如果要修改成员,为什么首先将其标记为const

        另外,对我来说,can_send 似乎具有 getter 语义,因此从逻辑上讲它不应该修改成员(我认为这里的错误是您尝试修改 packet_generating_rate,而不是创建方法 const

        【讨论】:

          【解决方案4】:

          一个像this这样的const成员函数

          bool Traffic_source::can_send(void) const
          

          不允许修改该类的任何成员变量。当您在此函数中修改成员变量时,这就是您收到错误的原因。将函数设为非 const,您将不会收到此错误。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-09-24
            • 1970-01-01
            • 2016-05-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多