Newbie: array of pointers

  • Thread starter Francesco Gallarotti
  • Start date
F

Francesco Gallarotti

My idea is that GElement should have an array of pointers to the Vertex
objects that compose the GElement.

If I declare:

Vertex **vertex;

as one of my private members of class GElement, and I write:

GElement(Vertex *v1, Vertex *v2, Vertex *v3) {
cout << "creating triangle:"<<endl<<*v1<<*v2<<*v3;
vertices = 3;
vertex[0] = v1; <<<<<<<<<<<< the program crashes here... can anybody
tell me why?
vertex[1] = v2;
vertex[2] = v3;
}; // set the element to represent a triangle

any suggestions?
 
?

=?iso-8859-1?Q?Juli=E1n?= Albo

Francesco Gallarotti escribió:
My idea is that GElement should have an array of pointers to the Vertex
objects that compose the GElement.

If I declare:

Vertex **vertex;

as one of my private members of class GElement, and I write:

GElement(Vertex *v1, Vertex *v2, Vertex *v3) {
cout << "creating triangle:"<<endl<<*v1<<*v2<<*v3;
vertices = 3;
vertex[0] = v1; <<<<<<<<<<<< the program crashes here... can anybody
tell me why?

Apparently you don't have initialized vertex, then it points to
whatever.

Regards.
 
K

Kevin Goodsell

Francesco said:
My idea is that GElement should have an array of pointers to the Vertex
objects that compose the GElement.

If I declare:

Vertex **vertex;

as one of my private members of class GElement, and I write:

GElement(Vertex *v1, Vertex *v2, Vertex *v3) {

Wait, you implied GElement is a class. Did you mean to write

GElement::GElement(...)

here?
cout << "creating triangle:"<<endl<<*v1<<*v2<<*v3;

You should terminate lines of output with a newline.

Also, the Vertex pointers could be invalid. Dereferencing them before
checking is probably a bad idea. Also, don't flush the stream (using
endl) when it's not necessary.
vertices = 3;

Another class member, I assume.
vertex[0] = v1; <<<<<<<<<<<< the program crashes here... can anybody
tell me why?

vertex has not been given a value yet. You tried to dereference an
invalid pointer. This is undefined behavior, and a crash is pretty typical.
vertex[1] = v2;
vertex[2] = v3;
}; // set the element to represent a triangle

No semicolon here.
any suggestions?

Learn how pointers work, then avoid them.

One immediate solution would be to use something like this:

// Note: vertex is now defined like this:
// vector<Vertex> vertex;

GElement::GElement(const Vertex &v1, const Vertex &v2, const Vertex &v3)
{
cout << "creating triangle:\n" << v1 << v2 << v3 << endl;
vertices = 3;
vertex.push_back(v1);
vertex.push_back(v2);
vertex.push_back(v3);
}

-Kevin
 
F

Francesco Gallarotti

GElement(Vertex *v1, Vertex *v2, Vertex *v3) {
Wait, you implied GElement is a class. Did you mean to write

GElement::GElement(...)

here?

Well that was part of my header files... the constructor was defined there
b/c laziness
You should terminate lines of output with a newline.

Both Vertex and GElement have << overloaded and Vertex is adding a new line
already
vertex[1] = v2;
vertex[2] = v3;
}; // set the element to represent a triangle

No semicolon here.

again I am in the header file here
Learn how pointers work, then avoid them.

One immediate solution would be to use something like this:

// Note: vertex is now defined like this:
// vector<Vertex> vertex;

GElement::GElement(const Vertex &v1, const Vertex &v2, const Vertex &v3)
{
cout << "creating triangle:\n" << v1 << v2 << v3 << endl;
vertices = 3;
vertex.push_back(v1);
vertex.push_back(v2);
vertex.push_back(v3);
}

I like this syntax (reminds me of Java Vectors) can you point me to some
tutorial for this? I cant find it on Deitel's book

Thanks for your kind help

F.
 
K

Kevin Goodsell

Francesco said:
Both Vertex and GElement have << overloaded and Vertex is adding a new line
already

I wouldn't recommend doing it that way. If printing a Vertex takes more
than one line, don't overload << for it. Use a Print() member function
instead. Unexpected newlines can cause problems in formatted output.
vertex[1] = v2;
vertex[2] = v3;
}; // set the element to represent a triangle

No semicolon here.


again I am in the header file here

Either way, you need to remove this semicolon.
I like this syntax (reminds me of Java Vectors) can you point me to some
tutorial for this? I cant find it on Deitel's book

I think the Dinkumware website has a library reference... here:

http://www.dinkumware.com/refxcpp.html

(starts on a copyright page) You can also try a web search for "C++
standard library".

-Kevin
 
K

Kevin Goodsell

Kevin said:
I think the Dinkumware website has a library reference... here:

http://www.dinkumware.com/refxcpp.html

(starts on a copyright page) You can also try a web search for "C++
standard library".

Also, if you want a good dead-tree reference, get "The C++ Standard
Library" by Nicolai Josuttis.

A good general C++ reference is "The C++ Programming Language" by Bjarne
Stroustrup.

A good C++ introduction text is "Accelerated C++" by Koenig & Moo.

-Kevin
 
F

Francesco Gallarotti

Both Vertex and GElement have << overloaded and Vertex is adding a new
line
I wouldn't recommend doing it that way. If printing a Vertex takes more
than one line, don't overload << for it. Use a Print() member function
instead. Unexpected newlines can cause problems in formatted output.

Ok I fixed that.
Either way, you need to remove this semicolon.

Interestingly enough with the semicolon I have no error
http://www.dinkumware.com/refxcpp.html

(starts on a copyright page) You can also try a web search for "C++
standard library".

thanks
 
K

Kevin Goodsell

Francesco said:
Interestingly enough with the semicolon I have no error

I'm not sure if it's an error or not. I think there are places where a
semicolon is optional, and some compilers accept semicolons where the
standard forbids them. It's best to leave out superfluous semicolons.

-Kevin
 
F

Francesco Gallarotti

Any idea why this works:

class GElement {
public:
GElement(Vertex *v1, Vertex *v2, Vertex *v3) {
cout << "creating triangle: "<<*v1<<"-"<<*v2<<"-"<<*v3<<endl;
vertices = 3;
vertex = new Vertex*[vertices];
vertex[0] = v1;
vertex[1] = v2;
vertex[2] = v3;
}; // set the element to represent a triangle

while this one does not compile?

class GElement {
public:
GElement(const Vertex &v1, const Vertex &v2, const Vertex &v3) {
cout << "creating triangle: "<<v1<<"-"<<v2<<"-"<<v3<<endl;
vertices = 3;
vertex = new Vertex*[vertices];
vertex[0] = v1;
vertex[1] = v2;
vertex[2] = v3;
}; // set the element to represent a triangle

I am confused... the way I see it is that the first one passes pointers to
objects of type Vertex.
The second one passes the address of the objects. Isn't that a pointer to,
in a way?
After all a point is just a memory location containing the address of the
first memory location of the object, isn't it?

F.
 
K

Kevin Goodsell

Francesco said:
Any idea why this works:

class GElement {
public:
GElement(Vertex *v1, Vertex *v2, Vertex *v3) {
cout << "creating triangle: "<<*v1<<"-"<<*v2<<"-"<<*v3<<endl;

When printing single characters, only pass a single character. It's a
minor thing, but you are wasting a few cycles making the runtime system
find the null-terminating character.

cout << "creating triangle: "<<*v1<<'-'<<*v2<<'-'<<*v3<<endl;
vertices = 3;
vertex = new Vertex*[vertices];

You've made your code even more dangerous. Now it's not only using
pointers (which you still haven't checked the validity of), it's also
using dynamic memory (odds are you will either fail to delete it, or do
so incorrectly).
vertex[0] = v1;
vertex[1] = v2;
vertex[2] = v3;
}; // set the element to represent a triangle

while this one does not compile?

class GElement {
public:
GElement(const Vertex &v1, const Vertex &v2, const Vertex &v3) {
cout << "creating triangle: "<<v1<<"-"<<v2<<"-"<<v3<<endl;
vertices = 3;
vertex = new Vertex*[vertices];
vertex[0] = v1;

This is a type mismatch. v1 is a (reference to a) Vertex. You cannot
implicitly convert a Vertex to a "pointer to Vertex".
vertex[1] = v2;
vertex[2] = v3;
}; // set the element to represent a triangle

I am confused... the way I see it is that the first one passes pointers to
objects of type Vertex.
The second one passes the address of the objects.

No, it passes references to the objects.
Isn't that a pointer to,
in a way?
No.

After all a point is just a memory location containing the address of the
first memory location of the object, isn't it?

Basically, but references aren't pointer. The semantics are different. A
reference acts, for all intents and purposes, as if it actually were the
object it refers to.

-Kevin
 
F

Francesco Gallarotti

vertices = 3;
vertex = new Vertex*[vertices];

You've made your code even more dangerous. Now it's not only using
pointers (which you still haven't checked the validity of), it's also
using dynamic memory (odds are you will either fail to delete it, or do
so incorrectly).

From what I understand, checking the validity means checking that they are
not NULL, or not 0.
What if I make a precondition of this constructor that those pointers must
be valid? The reason I am asking this is because this is a constructor. If
any of those pointers is null, well I can't leave the constructor and
"return" something.... Should I make the constructor doing nothing at all
and moving this whole business into a setVertices function??

Actually I did put a delete[] vertex inside the destructor, but I also put a
print statement there to check whether my program is going there when it
closes and I have never seen that printout coming on the screen. That makes
me feel like the object has not been destroyed.

Thank you very much for your help Kevin, I do really appreciate it!

Francesco
 
K

Kevin Goodsell

Francesco said:
vertices = 3;
vertex = new Vertex*[vertices];

You've made your code even more dangerous. Now it's not only using
pointers (which you still haven't checked the validity of), it's also
using dynamic memory (odds are you will either fail to delete it, or do
so incorrectly).


From what I understand, checking the validity means checking that they are
not NULL, or not 0.

Yes. NULL and 0 are the same thing (but when converted to a pointer, the
result need not be all-bits-zero).
What if I make a precondition of this constructor that those pointers must
be valid?

It would still be wise to check that the pre-condition is met. Note that
references cannot be null, so this would be unnecessary if you used
references instead of pointers.
The reason I am asking this is because this is a constructor. If
any of those pointers is null, well I can't leave the constructor and
"return" something.... Should I make the constructor doing nothing at all
and moving this whole business into a setVertices function??

The proper way to signal an error during construction is to throw an
exception. Actually, this is usually the proper way to indicate an error
in any kind of function.
Actually I did put a delete[] vertex inside the destructor,

Good... did you also provide a copy constructor and copy assignment
operator that properly handles self-assignment? If not, you are headed
for trouble. See the "rule of three." It should be in the FAQ, or you
should be able to find many references to it in the archives for this group.

None of this would be necessary however, if you avoided pointers. Or
but I also put a
print statement there to check whether my program is going there when it
closes and I have never seen that printout coming on the screen. That makes
me feel like the object has not been destroyed.

It should be, but it might depend on several things. First, how is the
object allocated? If it is 'new'ed, it obviously has to be 'delete'ed in
order to be destroyed. If it's an automatic local variable, it will be
deallocated when it goes out of scope. However, that can be bypassed if
your program terminates by using functions like exit() or abort().

If none of that describes your program, I'd say the most likely problem
is that your output statement in the destructor fails to properly
terminate the output with a newline (either via '\n' or endl). That can
cause output to not be displayed.

-Kevin
 
F

Francesco Gallarotti

I am a little frustrated.
Before my code was "dangerous" as you said, so I switched to use vectors and
I am getting so many errors:

Compiling...
dxfparser.cpp
gelement.h(34) : error C2872: 'ostream' : ambiguous symbol
gelement.h(34) : error C2872: 'ostream' : ambiguous symbol
dxfparser.cpp(13) : error C2872: 'ifstream' : ambiguous symbol
dxfparser.cpp(15) : error C2872: 'cout' : ambiguous symbol
dxfparser.cpp(30) : error C2872: 'cout' : ambiguous symbol
dxfparser.cpp(35) : error C2872: 'ifstream' : ambiguous symbol
dxfparser.cpp(41) : error C2872: 'cout' : ambiguous symbol
dxfparser.cpp(77) : error C2664: '__thiscall GElement::GElement(const class
Vertex &,const class Vertex &,const class Vertex &,const class Vertex &)' :
cannot convert parameter 1 from 'class Vertex *' to 'const class Vertex &'
Reason: cannot convert from 'class Vertex *' to 'const class Vertex'
No constructor could take the source type, or constructor overload
resolution was ambiguous
dxfparser.cpp(80) : error C2664: '__thiscall GElement::GElement(const class
Vertex &,const class Vertex &,const class Vertex &)' : cannot convert
parameter 1 from 'class Vertex *' to 'const class Vertex &'
Reason: cannot convert from 'class Vertex *' to 'const class Vertex'
No constructor could take the source type, or constructor overload
resolution was ambiguous
dxfparser.cpp(81) : error C2872: 'cout' : ambiguous symbol
dxfparser.cpp(81) : error C2679: binary '<<' : no operator defined which
takes a right-hand operand of type 'class GElement' (or there is no
acceptable conversion)
dxfparser.cpp(84) : error C2872: 'ifstream' : ambiguous symbol
dxfparser.cpp(92) : error C2872: 'cout' : ambiguous symbol
dxfparser.cpp(96) : error C2872: 'ifstream' : ambiguous symbol
dxfparser.cpp(100) : error C2872: 'ifstream' : ambiguous symbol
dxfparser.cpp(118) : error C2872: 'ifstream' : ambiguous symbol
Error executing cl.exe.

drawdxf.exe - 16 error(s), 0 warning(s)
 
K

Kevin Goodsell

Francesco said:
I am a little frustrated.
Before my code was "dangerous" as you said, so I switched to use vectors and
I am getting so many errors:

Do you have

using namespace std;

?

Did you #include <vector>, <iostream>, and <fstream>?

Compiling...
dxfparser.cpp
gelement.h(34) : error C2872: 'ostream' : ambiguous symbol
gelement.h(34) : error C2872: 'ostream' : ambiguous symbol
dxfparser.cpp(13) : error C2872: 'ifstream' : ambiguous symbol
dxfparser.cpp(15) : error C2872: 'cout' : ambiguous symbol
dxfparser.cpp(30) : error C2872: 'cout' : ambiguous symbol
dxfparser.cpp(35) : error C2872: 'ifstream' : ambiguous symbol
dxfparser.cpp(41) : error C2872: 'cout' : ambiguous symbol

These would appear to be symptoms of one of the problems I suggested above.
dxfparser.cpp(77) : error C2664: '__thiscall GElement::GElement(const class
Vertex &,const class Vertex &,const class Vertex &,const class Vertex &)' :
cannot convert parameter 1 from 'class Vertex *' to 'const class Vertex &'
Reason: cannot convert from 'class Vertex *' to 'const class Vertex'
No constructor could take the source type, or constructor overload
resolution was ambiguous
dxfparser.cpp(80) : error C2664: '__thiscall GElement::GElement(const class
Vertex &,const class Vertex &,const class Vertex &)' : cannot convert
parameter 1 from 'class Vertex *' to 'const class Vertex &'
Reason: cannot convert from 'class Vertex *' to 'const class Vertex'
No constructor could take the source type, or constructor overload
resolution was ambiguous

This appears to be the result of passing the wrong types to your
constructor. You need to pass Vector objects or references, not pointers.
dxfparser.cpp(81) : error C2872: 'cout' : ambiguous symbol

#include or namespace problem, probably.
dxfparser.cpp(81) : error C2679: binary '<<' : no operator defined which
takes a right-hand operand of type 'class GElement' (or there is no
acceptable conversion)

Could also be related to a #include or namespace problem, or the
operator is not visible for some reason.
dxfparser.cpp(84) : error C2872: 'ifstream' : ambiguous symbol
dxfparser.cpp(92) : error C2872: 'cout' : ambiguous symbol
dxfparser.cpp(96) : error C2872: 'ifstream' : ambiguous symbol
dxfparser.cpp(100) : error C2872: 'ifstream' : ambiguous symbol
dxfparser.cpp(118) : error C2872: 'ifstream' : ambiguous symbol

#include or namespace problem, probably.
Error executing cl.exe.

drawdxf.exe - 16 error(s), 0 warning(s)

-Kevin
 
F

Francesco Gallarotti

Ok now the errors are:

Compiling...
dxfparser.cpp
gelement.h(46) : error C2143: syntax error : missing ';' before '<'
gelement.h(46) : error C2501: 'vector' : missing storage-class or type
specifiers
gelement.h(46) : error C2059: syntax error : '<'
gelement.h(46) : error C2238: unexpected token(s) preceding ';'
dxfparser.cpp(77) : error C2664: '__thiscall GElement::GElement(const class
Vertex &,const class Vertex &,const class Vertex &,const class Vertex &)' :
cannot convert parameter 1 from 'class Vertex *' to 'const class Vert
ex &'
Reason: cannot convert from 'class Vertex *' to 'const class Vertex'
No constructor could take the source type, or constructor overload
resolution was ambiguous
dxfparser.cpp(80) : error C2664: '__thiscall GElement::GElement(const class
Vertex &,const class Vertex &,const class Vertex &)' : cannot convert
parameter 1 from 'class Vertex *' to 'const class Vertex &'
Reason: cannot convert from 'class Vertex *' to 'const class Vertex'
No constructor could take the source type, or constructor overload
resolution was ambiguous
Error executing cl.exe.

drawdxf.exe - 6 error(s), 0 warning(s)

this is the code for gelement.h:

#ifndef FG_GELEMENT
#define FG_GELEMENT

#include <iostream>
#include <vector>
#include <stdlib.h>
#include <stdio.h>
//using namespace std;

class GElement {
public:
GElement::GElement(const Vertex &v1, const Vertex &v2, const Vertex &v3) {
cout << "creating triangle:\n" << v1 << v2 << v3 << endl;
vertices = 3;
vertex.push_back(v1);
vertex.push_back(v2);
vertex.push_back(v3);
};
GElement::GElement(const Vertex &v1, const Vertex &v2, const Vertex &v3,
const Vertex &v4) {
cout << "creating triangle:\n" << v1 << v2 << v3 << endl;
vertices = 4;
vertex.push_back(v1);
vertex.push_back(v2);
vertex.push_back(v3);
vertex.push_back(v4);
};
~GElement() {
cout << "destroying GElement" << endl;
delete [] vertex;
}; // default destructor
bool isQuad(void) {return (vertices==4);}; // returns true if the element
is a quad
bool isTriangle(void) {return (vertices==3);}; // returns true if the
element is a line
Vertex getVertex(int v) {return vertex[v];}; // returns vertex index
friend ostream& operator <<(ostream& out, const GElement& element) {
out << "Element: " << endl;
out << "\tv0: " << element.vertex[0] << endl;
out << "\tv1: " << element.vertex[1] << endl;
out << "\tv2: " << element.vertex[2] << endl;
if(element.vertices==4)
out << "\tv3: " << element.vertex[3] << endl;
return out;
}; // for printing

private:
int vertices; // how many vertices
vector<Vertex> vertex; // vector of vertices
<<<<<<<<<<<<<<<<<<<<<<<<<<<line 46
};

#endif
 
K

Kevin Goodsell

Francesco said:
Ok now the errors are:

Compiling...
dxfparser.cpp
gelement.h(46) : error C2143: syntax error : missing ';' before '<'
gelement.h(46) : error C2501: 'vector' : missing storage-class or type
specifiers

It's called std::vector. You need either the fully-qualified name or
something like 'using namespace std;'.
gelement.h(46) : error C2059: syntax error : '<'
gelement.h(46) : error C2238: unexpected token(s) preceding ';'
dxfparser.cpp(77) : error C2664: '__thiscall GElement::GElement(const class
Vertex &,const class Vertex &,const class Vertex &,const class Vertex &)' :
cannot convert parameter 1 from 'class Vertex *' to 'const class Vert
ex &'
Reason: cannot convert from 'class Vertex *' to 'const class Vertex'
No constructor could take the source type, or constructor overload
resolution was ambiguous

You can't pass pointers where the function expects references.

GElement::GElement(const Vertex &v1, const Vertex &v2, const Vertex &v3) {
cout << "creating triangle:\n" << v1 << v2 << v3 << endl;
vertices = 3;
vertex.push_back(v1);
vertex.push_back(v2);
vertex.push_back(v3);
};

Still got these semicolons where they are either illegal or unnecessary.
GElement::GElement(const Vertex &v1, const Vertex &v2, const Vertex &v3,
const Vertex &v4) {
cout << "creating triangle:\n" << v1 << v2 << v3 << endl;
vertices = 4;
vertex.push_back(v1);
vertex.push_back(v2);
vertex.push_back(v3);
vertex.push_back(v4);
};
~GElement() {
cout << "destroying GElement" << endl;
delete [] vertex;

You can't delete what you didn't new.

<snip>

-Kevin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top