Reputation: 9
I know C pretty well (10 years) but am a C++ newbie. I am getting the following eror:
hw2.cpp: In function ‘int main()’:
hw2.cpp:337:7: error: no match for ‘operator=’ (operand types are ‘Graph’ and ‘Graph*’)
grph = new Graph(size);
^
hw2.cpp:337:7: note: candidate is:
hw2.cpp:17:7: note: Graph& Graph::operator=(const Graph&)
class Graph {
^
hw2.cpp:17:7: note: no known conversion for argument 1 from ‘Graph*’ to ‘const Graph&’
My class and constructor is :
class Graph {
//
// Class Graph -- contains the graph x, y of size Size showing connectivity
// (whether node X is connected to node Y) and the cost of
// the connection between X and Y.
//
private:
int nNodes;
vector<vector<int>> gph;
public:
//
// Constructors
//
explicit Graph(int size=50):nNodes(size){
gph = new int *[size];
for (int i = 0; i < size;i++)
gph[i] = new int[size];
}
//
// Destructors
//
~Graph(void){
retgph();
}
//
// Methods
//
void retgph(){
}
int getLength(
int x, // Node x
int y){ // Node y
return (gph[x][y]);
}
void setGraph(
int nodeX, // Node X
int nodeY, // Node Y
int value // Value to set it to.
){
gph[nodeX][nodeY]=value;
gph[nodeY][nodeX]=value;
return;
}
};
And my code in main is:
int main(){
Graph abc; // graph object.
Open opn; // open set object.
int final; // final node which should be destination.
const int size = 10;
const int source=0; // source node.
const int dest=5; // destination node.
abc = new Graph(size);
opn = new Open(size);
Please bear with me as I don't know what I am doing. I think ABC =NEW GRAPH(50) should instantiate an object ABC but the graph is built in the constructor Graph(int= size) and is GPH. What graph am I accessing when I say ABC.setNodeValue(1,2,3); ? The graph GPH in the class or another ABC instantiated? If it is the one instantiated (ABC) why does GPH appear in the class Graph at all? My thinking is that ABC is the one that will be manipulated by the methods (ABC.getNodeValue(47);) . Does GPH in the class just appear there as a model for the instantiation process? Also GPH is actually INT **GPH; . Any help you can give me would be greatly appreciated.
Upvotes: 0
Views: 214
Reputation: 595782
Inside your Graph
class, the gph
member is a std::vector
containing std::vector
elements. std::vector
is a wrapper for new[]
and delete[]
, so there is no need to use them directly to allocate the vectors. To change a std::vector
's size at runtime, you can use its resize()
method instead, eg:
class Graph {
private:
vector< vector<int> > gph;
public:
explicit Graph(int size=50) {
gph.resize(size);
for (int i = 0; i < size; ++i)
gph[i].resize(size);
}
/* You can even reduce the constructor even more,
using the constructor initialization list, if you
don't mind a little extra overhead temporarily...
explicit Graph(int size=50)
: gph(size, std::vector<int>(size) ) {
}
*/
/* not necessary to clear the vector during destruction,
it is handled automatic by the vector's own destructor...
~Graph() {
retgph();
}
*/
void retgph() {
gph.clear();
}
int getLength(int x, int y) {
return gph[x][y];
}
void setGraph(int x, int y, int value) {
gph[x][y] = value;
}
};
As for the rest off your code...
The new
operator returns a pointer to a newly instantiated object that is allocated on the heap. So new Graph
allocates a Graph
object, calls the Graph()
constructor on it, and returns a Graph*
pointer to that object.
Your compiler error is because your abc
variable is declared as a Graph
instantiated object on the stack instead of a Graph*
pointer. So, when you call abc = ...
, you are actually calling the Graph::operator=()
copy assignment operator (which in this case is auto-generated by the compiler for you). That operator expects a const Graph&
(reference to a constant Graph
object) as input, not a Graph*
(pointer to a Graph
object), thus the "no known conversion from Graph*
to const Graph&
" compiler error.
Same thing for your opn
variable, using the Open
class.
Change the abc
and opn
variables into pointers, and change any .
to ->
when accessing methods of those objects. And don't forget to delete
the objects when you are done using them:
int main() {
const int size = 10;
Graph *abc; // pointer to graph object.
Open *opn; // pointer to open set object.
abc = new Graph(size);
opn = new Open(size);
//...
abc->setGraph(x, y, value);
opn->doSomething(parameters);
//...
delete opn;
delete abc;
}
Or, use a std::auto_ptr
or std::unique_ptr
to handle the delete
for you:
#include <memory>
int main() {
const int size = 10;
std::uninque_ptr<Graph> abc( new Graph(size) );
std::unique_ptr<Graph> opn( new Open(size) )
//...
abc->setGraph(x, y, value);
opn->doSomething(parameters);
//...
}
Or, just keep instantiating them on the stack, but get rid of new
and delete
, and let them destruct themselves when they go out of scope when main()
exits:
int main() {
const int size = 10;
Graph abc(size);
Open opn(size);
//...
abc.setGraph(x, y, value);
opn.doSomething(parameters);
//...
}
Now, to answer your questions:
I think ABC =NEW GRAPH(50) should instantiate an object ABC but the graph is built in the constructor Graph(int= size) and is GPH.
abc = new Graph(50)
instantiates a new Graph
object with a constructor value of 50, and then assigns that object pointer to abc
. Internally, the Graph
constructor instantiates the gph
vectors using the specified size
.
What graph am I accessing when I say ABC.setNodeValue(1,2,3); ? The graph GPH in the class or another ABC instantiated?
You are accessing the abc
object, which internally accesses the gph
vectors.
If it is the one instantiated (ABC) why does GPH appear in the class Graph at all?
It is a piece of data that is inside of the abc
object. Think of Graph
as an envelope, and gph
as a thing inside of the envelope, and abc
as the hand that is holding the envelope. Each time new Graph
is called, a new envelope is created with a new gph
inside of it.
My thinking is that ABC is the one that will be manipulated by the methods (ABC.getNodeValue(47);) .
Yes.
Does GPH in the class just appear there as a model for the instantiation process?
No. It is one of the things being instantiated.
Also GPH is actually INT **GPH;`
Not in the code you have shown. But logically, that is equivalent to how a 2-dimensional std::vector
behaves at runtime - a pointer (inside the outer vector) to a dynamic array (what the outer vector manages) of pointers (the inner vectors) to dynamic arrays (what the inner vectors manage) of integers (what the inner vectors hold).
The C equivalent of the above code would look something like this:
struct Graph {
int size;
int **gph;
};
struct Open {
//...
};
Graph* createGraph(int size=50) {
Graph *g = (Graph*) malloc(sizeof(Graph));
g->size = size;
g->gph = (int**) malloc(sizeof(int**) * size);
for (int i = 0; i < size; ++i)
gph[i] = (int*) malloc(sizeof(int) * size);
return g;
}
Open* createOpen(int size=50) {
Open *o = (Open*) malloc(sizeof(Open));
//...
return o;
}
void retGraph(Graph *g) {
for (int i = 0; i < g->size; ++i)
free(gph[i]);
free(g->gph);
g->gph = NULL;
g->size = 0;
}
void freeGraph(Graph* g) {
retGraph(g);
free(g);
}
void freeOpen(Open* o) {
//...
free(o);
}
int getLength(Graph *g, int x, int y) {
return g->gph[x][y];
}
void setGraph(Graph *g, int x, int y, int value) {
g->gph[x][y] = value;
}
void doSomething(Open *o, parameters) {
//...
}
int main() {
const int size = 10;
Graph *abc = createGraph(size);
Graph opn = createOpen(size)
//...
setGraph(abc, x, y, value);
doSomething(opn, parameters);
//...
freeOpen(opn);
freeGraph(abc);
}
Upvotes: 0
Reputation: 2133
When you initially say Graph abc;
you are constructing a Graph
object on the stack (using it's default constructor, which in this case is a defaulted conversion constructor giving the graph a size of 50).
You then try to assign something of type Graph *
to this variable, as that is what new
returns (a pointer to the newly constructed object on the heap), which clearly isn't the same type as what the variable is. This is why the compiler is complaining about the lack of an operator=
(assignment operator) between those types, and is suggesting that you meant to use the copy assignment operator instead as it is a close match to what you're trying to do, but still not correct. Perhaps you are trying to do something such as:
const int size = 10;
Graph abc(size);
Open opn(size);
Or perhaps if you do require that they are stored via pointer:
const int size = 10;
Graph *abc = new Graph(size);
Open *opn = new Open(size);
// Do stuff...
delete opn;
delete abc;
Upvotes: 2