trouble accessing member functions in vectors of objects

Pages: 12
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
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);
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<().
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?
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
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);	
	}
}

Any ideas here? I'm still stuck.
for bezierSpline.erase, try this code: bezierSpline.erase(bezierSpline.begin()+i);

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?

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
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
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());

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
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)
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&);.
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?
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.
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.

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
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