противоречивый - PullRequest
       10

противоречивый

2 голосов
/ 14 октября 2010

У меня есть следующий класс

class node {
public:
    node() { }
    node(const node&);
    node(luint inID) { ID = inID; }
    ~node() { neighbors.clear(); }

    node& operator=(const node&);
    void addNeighbor(luint);
    void addNeighbor(const std::vector<luint>& );
    void setID(luint inID) { ID = inID; }
    luint getID() const { return ID; }
    std::vector<luint> & getNeighbors() const { return neighbors; }
protected:
    luint ID;
    std::vector<luint> neighbors;
};
void node::addNeighbor(const std::vector<luint>& inID) {
    for(int i = 0; i < inID.size(); i++)
        neighbors.push_back( inID[i] );
}
// etc..

сейчас я получаю ошибку

graph.h: In member function 'std::vector<long unsigned int, std::allocator<long unsigned int> >& node::getNeighbors() const': In file included from main.cpp:10:
graph.h:28: error: invalid initialization of reference of type 'std::vector<long unsigned int, std::allocator<long unsigned int> >&' from expression of type 'const std::vector<long unsigned int, std::allocator<long unsigned int> >'
make[2]: *** [build/Debug/GNU-MacOSX/main.o] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2

с другой стороны, если я уберу "const" при объявлении функции "getNeighbors ()", я получу ошибку

graph.cpp: In member function 'void graph::addNode(const node*)':
graph.cpp:36: error: request for member 'addNeighbor' in '((graph*)this)->graph::nodeMap. std::map<_Key, _Tp, _Compare, _Alloc>::operator[] [with _Key = long unsigned int, _Tp = node*, _Compare = std::less<long unsigned int>, _Alloc = std::allocator<std::pair<const long unsigned int, node*> >](((const long unsigned int&)((const long unsigned int*)(& inNode-> node::getID()))))', which is of non-class type 'node*'
graph.cpp:36: error: passing 'const node' as 'this' argument of 'std::vector<long unsigned int, std::allocator<long unsigned int> >& node::getNeighbors()' discards qualifiers
make[2]: *** [build/Debug/GNU-MacOSX/graph.o] Error 1

Кто-нибудь знает, как решить эту проблему?

Заранее спасибо,

<ч />

Обновление:

class node {
public:
    node() { }
    node(const node&);
    node(luint inID) { ID = inID; }
    ~node() { neighbors.clear(); }

    node& operator=(const node&);
    void addNeighbor(luint);
    void addNeighbor(const std::vector<luint>& );
    void setID(luint inID) { ID = inID; }
    luint getID() const { return ID; }
    std::vector<luint> & getNeighbors() { return neighbors; }
    std::vector<luint> const & getNeighbors() const { return neighbors; }
protected:
    luint ID;
    std::vector<luint> neighbors;
};

class graph {
public:
    graph() { }
    ~graph() { }

    void addNode(const node*);
    void addNode(const node&);
protected:
    std::map<luint, node*> nodeMap;
};

void node::addNeighbor(luint inID) {
    neighbors.push_back(ID);
}

void node::addNeighbor(const std::vector<luint>& inID) {
    for(int i = 0; i < inID.size(); i++)
        neighbors.push_back( inID[i] );
}

void graph::addNode(const node* inNode) {
    nodeMap[inNode->getID()] = new node(inNode->getID());
    nodeMap[inNode->getID()].addNeighbor( inNode->getNeighbors() );
}

void graph::addNode(const node& inNode) {
    nodeMap[inNode.getID()] = new node(inNode.getID());
}

Ошибка компиляции:

graph.cpp: In member function 'void graph::addNode(const node*)':
graph.cpp:36: error: request for member 'addNeighbor' in '((graph*)this)->graph::nodeMap. std::map<_Key, _Tp, _Compare, _Alloc>::operator[] [with _Key = long unsigned int, _Tp = node*, _Compare = std::less<long unsigned int>, _Alloc = std::allocator<std::pair<const long unsigned int, node*> >](((const long unsigned int&)((const long unsigned int*)(& inNode-> node::getID()))))', which is of non-class type 'node*'
make[2]: *** [build/Debug/GNU-MacOSX/graph.o] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2

Ответы [ 5 ]

2 голосов
/ 14 октября 2010

Так как ваш метод const, он должен работать с указателем const this, что означает, что вы не можете изменить любое поле текущего экземпляра (как будто все они const);это также означает, что вы не можете вернуть не const ссылку на neighbors, потому что все, что у вас есть, - const доступ к этому полю.

Чтобы устранить проблему, вы должны вернуть constссылка для const версии getNeighbors (используется, когда у клиента есть ссылка const или указатель на экземпляр вашего класса, чтобы он не мог изменить содержимое neighbors через ссылку)и «нормальная» ссылка для не const версии этого метода.Это известно как const -нагрузка .

// Non-const overload
std::vector<luint> & getNeighbors() { return neighbors; }
// const overload
std::vector<luint> const & getNeighbors() const { return neighbors; }

Для новой ошибки: вместо стрелки используется оператор точки (необходим для доступа к элементам объекта, на который ссылается указатель).

neighbors->push_back(ID);
2 голосов
/ 14 октября 2010

Если я правильно понимаю, это должно быть так:

std::vector<luint> const & getNeighbors() const { return neighbors; }
1 голос
/ 14 октября 2010

Я изменил код явным приведением, и он работает

class node {
    friend class graph;
    friend ostream& operator<< (ostream&, const node&);
public:
    node() { }
    node(const node&);
    node(luint inID) { ID = inID; }
    ~node() { neighbors.clear(); }

    node& operator=(const node&);
    void addNeighbor(luint);
    void addNeighbor(const std::vector<luint>& );
    luint getID() const { return ID; }


protected:
    luint ID;
    std::vector<luint> neighbors;
};

class graph {
    friend ostream& operator<< (ostream&, graph&);
public:
    graph() { }
    ~graph() { }

    void addNode(const node& );
    void addNode(const node* );
    void readFile(const char * );
    void clearMap();
protected:
    std::map<luint, node*> nodeMap;
};

void graph::addNode(const node& inNode) {
    nodeMap[ (const luint)inNode.ID ] = new node( (const luint) inNode.ID );
    nodeMap[ (const luint)inNode.ID ]->neighbors.resize( (const luint) inNode.neighbors.size() );
    *nodeMap[ (const luint)inNode.ID ] = inNode;
}
1 голос
/ 14 октября 2010

Постоянная квалифицированная функция-член обещает не изменять состояние объекта. Это ключ для запоминания.

Теперь, если такая функция-член позволяет возвращать ссылку на элемент, так что вызывающая сторона может изменять элемент, функция нарушает обещание сохранения неизменности объекта.

Исправление включает в себя создание возвращаемого типа в качестве «ссылки на const» (std :: vector const)

0 голосов
/ 14 октября 2010

Прочитайте эту C ++ FAQ запись . Вы не можете объявить addNeighbours как const, если возвращаете неконстантную ссылку на переменную-член.

...