trouble accessing member functions in vectors of objects

Pages: 12
Sep 2, 2010 at 7:37pm
Hi All,

I'm writing a short program that uses Bezier Splines and decided to create an object to contain all the integers necessary for each vertex. The vertices are stored in a vector so that I can iterate through them to draw the spline while taking advantage of vector's member functions.

The problem is that I'm getting "no matching function" errors for erase() and push_back(). I'm also having trouble with sort() for the std algorithm package. I think both have to do with referencing of my arguments, although I don't really understand what the problem is.

I define the vector without a pointer as follows:

<code>
vector<bezierVertex> bezierSpline;.
</code>

Then, I call the functions with the dot operator:

<code>
bezierSpline.erase(bezierSpline[i]);
bezierSpline.push_back(new bezierVertex(parent->mouseX, parent->mouseY));
sort(bezierSpline.begin(), bezierSpline.end(), bezierSpline.pointX);
</code>

The third argument to sort() is the integer I want the bezierVertex classes sorted by.

What is the correct way to do this?

Thanks,
Zach
Sep 2, 2010 at 7:56pm
bezierSpline.push_back(new bezierVertex(parent->mouseX, parent->mouseY));

Have you come from a java background by any chance?

The code bezierSpline.erase(bezierSpline[i]); will not work as the erase() function is expecting a position in the vector "bezierSpline" as an argument. Change the line to: bezerSpline.erase(i);
Sep 2, 2010 at 7:59pm
std::sort() doesn't work that way. If the class doesn't overload operator<(), the third parameter for std::sort() has to be either a function with the signature bool f(const T &,const T &); (T being the relevant type) that returns true if the first parameter is < the second one; or an object of a class that overloads operator()() with the same signature as the previous function.

In short, the simplest way to do it is to just have bezierVertex overload operator<().
Sep 2, 2010 at 8:23pm
Mcleano- yes, Java background plus some C in specialized applications. It's been surprisingly tough to adjust to C++. I've found this site has the best tutorials, but after reading the pointer one numerous times I still don't feel like I have a good grasp on where to use them practically. I think I at least get the stack/heap distinction, though. Anyway, the foundation of this project was ported form Java, so I added the parent variable to maintain the same

I actually originally tried bezerSpline.erase(i);, but still get the same error.

Helios, there are many things I don't understand in your response. Are you saying that the definition of bezierVertex should include something like this: bool operator<(const T &,const T &); and then I can just pass it the int?
Sep 2, 2010 at 9:47pm
Yeah I thought so. Due to the stack/heap stuff adding 'new' where you did doesn't work in C++ like it does in Java. You could however achieve what you wanted by removing the new and laeving it like that.

Could you please post the code that involves the line: bezierSpline.erase(bezierSpline[i]); for further help.
Last edited on Sep 2, 2010 at 9:49pm
Sep 3, 2010 at 3:06am
Thanks. I actually copied that line wrong. It should have read bezierSpline.erase(bezierVertex[i]);. The context is pretty simple:

1
2
3
4
5
for(int i = 0; i < bezierSpline.size(); i++){
	if(bezierSpline[i].pointY <= parent->mouseY + 5 && bezierSpline[i].pointY >= parent->mouseY - 5){
		bezierSpline.erase(i);	
	}
}

Sep 3, 2010 at 9:27pm
Any ideas here? I'm still stuck.
Sep 3, 2010 at 10:27pm
for bezierSpline.erase, try this code: bezierSpline.erase(bezierSpline.begin()+i);

Sep 3, 2010 at 10:57pm
Thanks!

That just leaves the sort function, for which I didn't understand the response. For a vector of objects how do I tell sort() what variable to sort by?
Sep 6, 2010 at 8:56am

That just leaves the sort function, for which I didn't understand the response. For a vector of objects how do I tell sort() what variable to sort by?


Assuming you are using STL algorithm sort function, there is one version which takes a third argument and it is this argument you passed in which will tell the sort function to sort based on what variable.

http://www.cplusplus.com/reference/algorithm/sort/

Refer to above API description.
Last edited on Sep 6, 2010 at 8:56am
Sep 6, 2010 at 2:45pm
That was what I was trying to do with sort(bezierSpline.begin(), bezierSpline.end(), bezierSpline.pointX);, but I get an error. There was a comment above about overloading it, but I don't understand it.

Thanks,
Zach
Sep 6, 2010 at 3:54pm
1
2
3
4
5
6
7
8
class A{
public:
	static bool compareX(const A&, const A&); //static so you don't need an object to call it
        static bool compareY(const A&, const A&);
};
//and you call
sort(v.begin(), v.end(), A::compareX);
sort(v.begin(), v.end(), A::compareY);

You can avoid the third parameter in sort if your class has overloaded operator < (but you can't choose that way)
1
2
3
4
5
6
class A{
public:
	bool operator<(const A&) const; //now you can do a < b
};

sort(v.begin(), v.end());

Sep 6, 2010 at 11:33pm
A little more explanation would help. What is A in relation to my example? I have a vector (bezierSpline) of objects (bezierVertex), which I want to sort based on an int in that object (pointX).

Thanks,
Zach
Sep 7, 2010 at 1:00am
I just don't want to write so much. The class A is your class bezierVertex, the vector v is your vector bezierSpline.
The third argument of the sort is the compare function (if you don't put anything it will take the less function, i.e. operator<).
To avoid losing the encapsulation I suggest you to use an static method, instead of an outside function (compareX will say if an object is less than other based on the pointX attribute)
Sep 7, 2010 at 1:37am
I just don't understand where in all that I specify that pointX is the variable I want it to sort based on, rather than any of the other integers I have in bezierVertex. And I get an odd error from this: static bool compareX(const bezierVertex&, const bezierVertex&);.
Sep 7, 2010 at 2:17am
1
2
3
sort(v.begin(), v.end(), A::compareX); // use the compareX funtion
//and in A::compareX you'll have something like this
return a.pointX < b.pointX;


What is the error that you're getting?
Sep 7, 2010 at 3:49am
comp
Comparison function object that, taking two values of the same type than those contained in the range, returns true if the first argument goes before the second argument in the specific strict weak ordering it defines, and false otherwise.

Above is from the API description.

I believe bezierSpline.pointX is a int variable inside the object bezierSpline ? Then it does not fit the above third argument requirement isn't it ?

You may want to read up on C++ STL function object material to know what STL mean by function object.
Sep 7, 2010 at 3:59am
To avoid losing the encapsulation I suggest you to use an static method, instead of an outside function (compareX will say if an object is less than other based on the pointX attribute)


It actually depend on your situation. Having outside function can help in below example.

E.g
class CompareX {
private:
int const_1; in const_2;
public:
CompareX(int x, int y) { const_1 = x; const_2 = y; }
bool operator()(const X& o1, const X& o2) {
//some business logic using const_1 and const_2 with o1 and o2
//etc etc
return o1.pointX > o2.pointX;
}
};

Then I can have CompareX(10,4) for one sort call. CompareX(8,4) for another sort call.
Sep 7, 2010 at 1:31pm

You may want to read up on C++ STL function object material to know what STL mean by function object.

I'm confused. http://www.cplusplus.com/reference/algorithm/sort/ uses a function in the example.


Well you could use a wrapper too. You can justify it if an object can't determine if is less than another.
In your example you are breaking the encapsulation
Sep 10, 2010 at 9:24pm
Here is my function:

1
2
3
static bool bezierVertex:compareX(const bezierVertex A, const bezierVertex B){
	return A.pointX<B.pointX;
}


It throws the error "Function definition does not declare parameters."
Pages: 12