我正在为类实现Graph结构。简而言之,在尝试编译测试程序时,我对复制构造函数的调用会导致问题:
Graph.h: In copy constructor `Graph::Graph(Graph&) [with Object = int, Weight = int]': gtest.cpp:16: instantiated from here Graph.h:129: error: base operand of `->' has non-pointer type `Graph' gtest.cpp:16: instantiated from here Graph.h:131: error: base operand of `->' has non-pointer type `Graph'
有问题的行在这里:
template<typename Object,typename Weight> //copy constructor
Graph<Object,Weight>::Graph(Graph<Object,Weight>& G){
for(int i=0; i<(G.edge).size(); ++i) //129
edge[i] = G.edge[i];
for(int j=0; j<(G.vertex).size(); ++j) //131
vertex[j] = G.vertex[j];
counter = G.counter;
}
...但这对我没有意义,因为我使用的是“。”,而不是“ - &gt;”。如果我不是(或者至少我认为我不是)处理指针,为什么它甚至会提到箭头?
作为参考,我到目前为止的图表实现如下(它是不完整的;请忽略缺失的部分和/ DONE? / comments):
**编辑:在此之前,我将添加gtest.cpp文件,其中调用了复制构造函数。所有其他部分都可以正常工作:
#include "Graph.h"
int main(){
Graph<int, int> g;
g.insertVertex(8);
g.insertVertex(256);
g.insertVertex(32);
g.insertVertex(7);
g.insertEdge((g.vertices())[0], (g.vertices())[1], 457);
g.insertEdge((g.vertices())[2], (g.vertices())[1], 457);
g.insertEdge((g.vertices())[1], (g.vertices())[3], 457);
Graph<int, int> g2 = g;
g.print();
}
#ifndef GRAPH_H
#define GRAPH_H
#include <list>
#include <vector>
#include <limits.h>
#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
template<typename Object,typename Weight>
class Graph{
public:
class Vertex;
class Edge{
public:
Edge(Vertex* v,Vertex* w,Weight setweight){
start = v;
end = w;
v->edge.push_back(this);
w->inedge.push_back(this);
weight = setweight;
explored = false;
}
Edge(){
explored = false;
}
Weight weight;
Vertex* start;
Vertex* end;
bool explored;
};
class Vertex{
public:
Vertex(Object setelement){
level = 0;
connectedcomponent = 0;
element = setelement;
back = NULL;
explored = false;
}
Vertex(){
level = 0;
connectedcomponent = 0;
back = NULL;
explored = false;
}
Object element;
vector<Edge*> edge;
vector<Edge*> inedge;
double value;
unsigned int starttime, finishtime;
unsigned int level;
unsigned int connectedcomponent;
float rank;
Vertex* back;
int color;
bool explored;
};
/////////////////////////////////////////////////////////////////////////
private:
vector<Edge*> edge;
vector<Vertex*> vertex;
unsigned int counter;
public:
/////////////////////////////////////////////////////////////////////////
Graph();
Graph(Graph& G);
~Graph();
void reset();
void resetBack();
void resetValues();
void resetLevels();
void resetExplored();
void resetConnectedComponents();
vector<Vertex*> incidentVertices(Vertex* v);
vector<Edge*> incidentEdges(Vertex* v);
vector<Edge*> outgoingEdges(Vertex* v);
vector<Vertex*> adjacentVertices(Vertex* v);
unsigned int indegree(Vertex* v);
unsigned int outdegree(Vertex* v);
unsigned int degree(Vertex* v);
Vertex* startVertex(Edge* e);
Vertex* endVertex(Edge* e);
// is there an edge from v to w ?
bool isAdjacent(Vertex* v,Vertex* w);
Vertex* insertVertex(Object o);
void insertEdge(Vertex* v,Vertex* w,Weight t);
void insertUndirectedEdge(Vertex* v,Vertex* w,Weight t);
void removeVertex(Vertex* v);
void removeEdge(Edge* e);
unsigned int numVertices();
unsigned int numEdges();
vector<Vertex*> vertices();
vector<Edge*> edges();
void print();
/////////////////////////////////////////////////////////////////////////
};
/*DONE?*/template<typename Object,typename Weight>
Graph<Object,Weight>::Graph() :edge(0), vertex(0), counter(0) {}
/*DONE?*/template<typename Object,typename Weight> //copy constructor
Graph<Object,Weight>::Graph(Graph<Object,Weight>& G){
for(int i=0; i<(G.edge).size(); ++i)
// edge[i] = G.edge[i];
for(int j=0; j<(G.vertex).size(); ++j)
// vertex[j] = G.vertex[j];
counter = G.counter;
}
/*DONE?*/template<typename Object,typename Weight> //destrutor
Graph<Object,Weight>::~Graph(){}
/*DONE*/template<typename Object,typename Weight>
void Graph<Object,Weight>::reset(){
counter = 0;
resetBack();
resetValues();
resetLevels();
resetExplored();
resetConnectedComponents();
}
/*DONE*/template<typename Object,typename Weight>
void Graph<Object,Weight>::resetBack(){
for(unsigned int i=0;i<vertex.size();i++)
vertex[i]->back = NULL;
}
/*DONE*/template<typename Object,typename Weight>
void Graph<Object,Weight>::resetValues(){
for(unsigned int i=0;i<vertex.size();i++)
vertex[i]->value = INT_MAX;
}
/*DONE*/template<typename Object,typename Weight>
void Graph<Object,Weight>::resetLevels(){
for(unsigned int i=0;i<vertex.size();i++)
vertex[i]->level = 0;
}
/*DONE*/template<typename Object,typename Weight>
void Graph<Object,Weight>::resetExplored(){
for(unsigned int i=0;i<vertex.size();i++)
vertex[i]->explored = false;
}
/*DONE*/template<typename Object,typename Weight>
void Graph<Object,Weight>::resetConnectedComponents(){
for(unsigned int i=0;i<vertex.size();i++)
vertex[i]->connectedcomponent = 0;
}
/*DONE?*/template<typename Object,typename Weight> //concatenate incoming and outgoing edge lists and return vector of total inc. edges
vector<typename Graph<Object,Weight>::Edge*> Graph<Object,Weight>::incidentEdges(Vertex* v){
(v->edge).insert((v->edge).end(), (v->inedge).begin(), (v->inedge).end());
return v->edge;
}
/*DONE?*/template<typename Object,typename Weight> //return vector of outgoing edges
vector<typename Graph<Object,Weight>::Edge*> Graph<Object,Weight>::outgoingEdges(Vertex* v){
return v->edge;
}
/*DONE?*/template<typename Object,typename Weight>
vector<typename Graph<Object,Weight>::Vertex*> Graph<Object,Weight>::incidentVertices(Vertex* v){
vector<Vertex*> result;
for(int i=0; i<(v->incidentEdges()).size(); ++i){
if((v->incidentEdges())[i].endVertex() == v) result.push_back((v->incidentEdges())[i].startVertex());
else result.push_back((v->incidentEdges())[i].endVertex()); //edges incident on vertex could be either direction
}
return result;
}
/*DONE?*/template<typename Object,typename Weight>
vector<typename Graph<Object,Weight>::Vertex*> Graph<Object,Weight>::adjacentVertices(Vertex* v){
vector<Vertex*> result;
for(int i=0; i<(v->incidentEdges()).size(); ++i){
if((v->incidentEdges())[i].startVertex() == v) result.push_back((v->incidentEdges())[i].endVertex()); }
return result;
}
/*DONE?*/template<typename Object,typename Weight>
unsigned int Graph<Object,Weight>::outdegree(Vertex* v){
return (v->adjacentVertices()).size();
}
/*DONE?*/template<typename Object,typename Weight>
unsigned int Graph<Object,Weight>::indegree(Vertex* v){
return ((v->incidentEdges()).size()) - ((v->adjacentVertices()).size()); //I <3 parentheses
}
/*DONE?*/template<typename Object,typename Weight>
unsigned int Graph<Object,Weight>::degree(Vertex* v){
return (v->incidentEdges()).size();
}
/*DONE?*/template<typename Object,typename Weight>
typename Graph<Object,Weight>::Vertex* Graph<Object,Weight>::startVertex(Edge* e){
return e->start;
}
/*DONE?*/template<typename Object,typename Weight>
typename Graph<Object,Weight>::Vertex* Graph<Object,Weight>::endVertex(Edge* e){
return e->end;
}
// is there an edge from v to w ?
/*DONE?*/template<typename Object,typename Weight>
bool Graph<Object,Weight>::isAdjacent(Vertex* v,Vertex* w){
if(degree(v) <= degree(w)){ /*look in smaller incidence collection...but must fulfill directional requirements*/
for(int i=0; i<(v->adjacentVertices()).size(); ++i) /*if directed edge is v to w, just check for adjacent vertex w*/
if((v->adjacentVertices())[i] == w) return true;
else return false; }
else{ /* if deg(w) < deg(v), look in w's incidence (not adjacency!) collection instead*/
for(int i=0; i<(w->incidentEdges()).size(); ++i){
if((w->incidentEdges())[i]->endVertex() == w) return true; /*badass-n. a person who keeps track of parentheses
*like these and programs entirely in PuTTY
*synonym: person too stubborn to take 5 minutes
*and learn Visual Studio*/
else return false; }
}
}
/*DONE?*/template<typename Object,typename Weight>
typename Graph<Object,Weight>::Vertex* Graph<Object,Weight>::insertVertex(Object o){
Vertex* v = new Vertex(o);
vertex.push_back(v); /*construct vertex and add it to Graph's vertex vector member*/
}
/*DONE?*/template<typename Object,typename Weight>
void Graph<Object,Weight>::insertEdge(Vertex* v,Vertex* w,Weight t){
Edge* e = new Edge(v, w, t);
edge.push_back(e);
}
/*DONE?*/template<typename Object,typename Weight>
void Graph<Object,Weight>::removeEdge(Edge* e){
edge.erase(std::find(edge.begin(), edge.end(), e)); /*remove it from overall Graph's edge vector*/
((edge.end()).incidentEdges()).erase(std::find(((edge.end()).incidentEdges()).begin(), ((edge.end()).incidentEdges()).end(), e));
/*...also from end vertex's incidence list...in the least confusing code possible, of course...*/
((edge.begin()).incidentEdges()).erase(std::find(((edge.begin()).incidentEdges()).begin(), ((edge.begin()).incidentEdges()).end(), e));
/*...and, finally, from begin vertex's incidence list*/
}
template<typename Object,typename Weight>
void Graph<Object,Weight>::insertUndirectedEdge(Vertex* v,Vertex* w,Weight t){
Edge* dir1 = new Edge(v,w,t);
edge.push_back(dir1); //Hmm...should I push back one or both? This thing messes up the counts!
Edge* dir2 = newEdge(w,v,t);
edge.push_back(dir2);
}
/*DONE?*/template<typename Object,typename Weight>
void Graph<Object,Weight>::removeVertex(Vertex* v){
vertex.erase(std::find(vertex.begin(), vertex.end(), v)); /*remove it from overall Graph's vertex vector*/
for(int i=0; i<(v->incidentEdges()).size(); ++i){
if((v->incidentEdges())[i].start == v)
(v->incidentEdges())[i].start = NULL;
else if((v->incidentEdges())[i].end == v)
(v->incidentEdges())[i].end = NULL; }
}
/*DONE?*/template<typename Object,typename Weight>
unsigned int Graph<Object,Weight>::numVertices(){
return vertex.size();
}
/*DONE?*/template<typename Object,typename Weight>
unsigned int Graph<Object,Weight>::numEdges(){
return edge.size();
}
/*DONE?*/template<typename Object,typename Weight>
vector<typename Graph<Object,Weight>::Vertex* > Graph<Object,Weight>::vertices(){
return vertex;
}
/*DONE?*/template<typename Object,typename Weight>
vector<typename Graph<Object,Weight>::Edge* > Graph<Object,Weight>::edges(){
return edge;
}
template<typename Object,typename Weight>
void Graph<Object,Weight>::print(){
cout << "vertices:" << endl;
for(unsigned int i=0;i<vertex.size();i++)
cout << vertex[i]->element << endl;
cout << "edges:" << endl;
for(unsigned int i=0;i<edge.size();i++)
cout << "(" << edge[i]->start->element << "," << edge[i]->end->element << ")" << endl;
}
#endif
答案 0 :(得分:0)
请再次检查问题出现的位置。像,
template <typename T, typename K>
struct A
{
T i;
A(){};
A(A&);
};
template <typename T, typename K>
A<T,K>::A(A<T,K>& that)
{
i=that.i;
}
int main()
{
A<int,int> _a;
A<int,int> _b(_a);
return 0;
}
是标准的,编译好。
答案 1 :(得分:0)
错误可能在于gtest.cpp第16行,它在Graph.h:129和:131中调用。看看那里。
也许size()函数有问题?
答案 2 :(得分:0)
WOW。哇哇。
事实证明,我的目录中有两个同名的“Graph.h”文件。当然,一个人老了,有' - &gt;'错误。我摆脱了它(它甚至到达那里我不知道),现在一切都运行良好。
感谢所有人的帮助!
P.S .--有没有人认为通过简单地将“无向边”成员添加到整个数据结构来容纳“insertUndirectedEdge”函数会是有利的?实现框架基本上是在没有它的情况下给我们的,教师说我们需要使用两个边(uv和vu)在两个顶点u和v之间形成一个无向的边。也许我错过了什么,但这似乎就像它会比它的价值更麻烦,特别是考虑到计数(顶点上的入射边缘的数量等)会使它复杂化。