2011-04-02 159 views
1

我是新來的C++,並一直試圖實施bellman福特算法, 我的程序doesnt編譯我得到下面的編譯器錯誤,這是相當神祕。編譯器錯誤的C++幫助

D:\ME\MCA\Sem2\LAB\DS\graph_algorithms>g++ bellman_ford.cpp -o bellman.exe 
In file included from bellman_ford.cpp:8:0: 
graph.h: In member function 'void Graph::print_distance_table()': 
graph.h:172:31: error: passing 'const Vertex' as 'this' argument of 'char Vertex::get_name()' discards qualifiers 

,我正在使用的文件是graph.h:

#ifndef GRAPH_H 
#define GRAPH_H 

class Vertex 
{ 
    private: 
    char vertex_name; 
    public: 
    Vertex(){}; 

    Vertex(const char n) 
    { 
     vertex_name = n; 
    } 
//Method signatures 
    char get_name(); 
//overloaded operators 
    bool operator==(Vertex other) const 
    { 
     if(vertex_name == other.get_name()) 
     { 
     return true; 
     } 
     else return false; 
    } 

    bool operator< (Vertex other) const 
    { 
     if(vertex_name - other.get_name() < 0) 
     { 
     return true; 
     } 
     else return false; 
    } 
}; 

class Edge 
{ 
    private: 
    Vertex source,destination; 
    int weight; 
    public: 
    Edge(){}; 
    Edge(Vertex v1,Vertex v2,int w) 
    { 
     source = v1; 
     destination = v2; 
     weight = w; 
    } 

    //Method signatures 
    Vertex get_source(); 
    Vertex get_destn(); 
    int get_weight(); 
}; 

class Graph 
{ 
    private: 
    list<Vertex> V; 
    list<Edge> E; 
    map<Vertex,int> distances; 
    public: 
    Graph(list<Vertex> vertex_list,list<Edge> edge_list) 
    { 
     V = vertex_list; 
     E = edge_list; 
    } 

//  Method Signatures 
    bool add_vertex(Vertex); 
    bool remove_vertex(Vertex); 
    bool add_edge(Edge); 
    bool remove_edge(Edge); 
    int total_vertices(); 
    int total_edges(); 
    void initialize_distances(Vertex); 
    void print_distance_table(); 
}; 


/* 
* Methods for the Vertex class are defined first 
*/ 

char Vertex::get_name() 
{ 
    return vertex_name; 
} 


/* 
* Methods for the Edge class are defined next 
*/ 

int Edge::get_weight() 
{ 
    return weight; 
} 

Vertex Edge::get_destn() 
{ 
    return destination; 
} 

Vertex Edge::get_source() 
{ 
    return source; 
} 

/* 
* Methods for our Graph class 
*/ 

bool Graph::add_vertex(Vertex u) 
{ 
    V.push_back(u); 
} 

bool Graph::add_edge(Edge e) 
{ 
    E.push_back(e); 
} 

//slightly more tricky will write code when it'll be required i.e. when i implement dfs or some other algo 
//that requires addition and removal of edges and vertices 
bool Graph::remove_vertex(Vertex u) 
{ 
    //first check if it exists 
    //when a vertex is removed then then all the edges that have it as either a source or a destination should also be removed 
} 

// 
bool Graph::remove_edge(Edge e) 
{ 
    //much easier than removing a vertex 
    //check if the edge exists and if it does remove it from the list.. 
} 

int Graph::total_edges() 
{ 
    return E.size(); 
} 

int Graph::total_vertices() 
{ 
    return V.size(); 
} 

void Graph::initialize_distances(Vertex source) 
{ 
    distances.clear(); 
    for(list<Vertex>::iterator it=V.begin(); it != V.end();it++) 
    { 
    //todo : overload = for the class vertex 
    if(*it == source) 
    { 
     distances[*it] = 0; 
    } 
    else 
    { 
     distances[*it] = INT_MAX; 
    } 
    } 
} 

void Graph::print_distance_table() 
{ 
    map<Vertex,int>::iterator mit; 
    for(mit = distances.begin(); mit != distances.end();mit++) 
    { 
    cout<<mit->first.get_name()<<"\t"<<mit->second<<endl; 
    } 
} 

#endif //GRAPH_H 

和bellman_ford.cpp

#include<iostream> 
#include<list> 
#include<map> 
#include<climits> 

using namespace std; 

#include "graph.h" 

int main() 
{ 
    Graph G = Graph(list<Vertex>(), list<Edge>()); 
    int vertices; 
    cout<<"Enter the no. of vertices : "; 
    cin>>vertices; 

    for(int i=0;i<vertices;i++) 
    { 
    cout<<"Enter the name of the vertex(one character only) : "; 
    char tmp; 
    cin>>tmp; 
    Vertex tmp_vertex = Vertex(tmp); 
    G.add_vertex(tmp_vertex); 
    } 

    char choice; 
    do 
    { 
    char tmp_src,tmp_destn; 
    int tmp_w; 
    cout<<"Enter edge(source, destn, weight)"; 
    cin>>tmp_src>>tmp_destn>>tmp_w; 
    G.add_edge(Edge(Vertex(tmp_src),Vertex(tmp_destn),tmp_w)); 

    cout<<"Add another edge (y|n)? "; 
    cin>>choice; 
    }while(choice != 'n'); 

    Vertex source_vertex; 
    cout<<"\nEnter the source vertex : "; 
    cin>>choice; 
    source_vertex = Vertex(choice); 
    G.initialize_distances(source_vertex); 

    //now to iterate over the graph and compute the new shortest distances 
    G.print_distance_table(); 


    return 0; 
} 

我不是很熟悉STL地圖這似乎成爲graph.h文件第172行中的錯誤源。 如果我刪除對mit-> first.get_name()的引用,那麼它可以工作,但我也希望打印頂點名稱。 我犯的這個錯誤是什麼錯誤?

回答

4

std::mapfirst(「關鍵」)元素爲const,因爲它們可能未被更改。您不能在const對象上調用非const成員函數,因此出現此錯誤。

解決方案是聲明Vertex::get_nameconstchar get_name() const;這是一個合同,告訴編譯器get_name()不會改變對象。

一般來說,這是一個很好的習慣。您應該始終聲明非變異成員函數爲const,因爲它允許編譯器發現錯誤。

+0

嘿非常感謝, 修復了這個問題。 但我的方法沒有修改頂點是否有必要我指定它爲const? – nikhil 2011-04-02 11:28:53

+1

@nikhil:是的,因爲在最一般的情況下,編譯器不一定知道成員函數不會修改任何內容。另外,'const'充當了很好的文檔,並且還可以防止你意外地在成員函數中意外地修改某些東西。 – 2011-04-02 11:35:17

2

您必須聲明與「const」限定符的方法:

const char* get_name() const; 

通過有很多,這將無法正常工作等事情的方式,但我把它留給你找出...

+0

如果我這樣做,那麼我將不得不改變我的代碼的一大堆, 另一個問題,我有關於語法是 爲什麼你寫一次開始一次,最後一次const? – nikhil 2011-04-02 11:31:23

+0

第一個const是函數返回類型聲明的一部分,它說函數get_name()返回一個指向const char的指針。第二個const說函數get_name()是一個const函數,即它不應該修改它被調用的對象中的任何數據。 – 2011-04-02 13:53:52