Passing reference of vector of objects as arguments in C++ - c++

I'm trying to build a function in which an argument is a reference to a vector of objects. In this case name of the object is 'obj', it is an instance of the class 'Example' and it is a vector as defined in vector class. Object have members like x, y and z.
The reason I'm trying with passing references is because I want to change the value of obj.z by making use of obj.x and obj.y from inside of the function.
#include <vector>
#include <iostream>
using namespace std;
class Example{
public:
double x;
double y;
double z;
Example()
: x(0.0),y(0.0){
}
};
void calculate(Example &obj, int M) {
for(int i = 0; i < M; i++) {
obj[i].z = obj[i].x * obj[i].y;
}
}
int main() {
vector<Example> obj;
int N = 10;
calculate(obj, N);
}
When I run this, I get the following errors:
Inside of the function I have: "Type 'Example' does not provide a subscript operator."
I google'd it and saw that it is related to operator overloading and usage of references. The solution is probably related to dereferencing my object reference inside of the function, but I wasn't able to manage this one right currently.
And the second error is outside of the function, inside the main() at the line where I call the function: "No matching function for call to 'calculate'".
Here, I assume the error is related to the fact that obj is not just an object but a vector of objects, so I should change the argument somehow. But I haven't been able to correct this one up to now as well.
So, to summarize, I want to pass a vector of objects to a function as reference, because I want to be able to change a member of the object inside of the function.
Thank you in advance.

I want to pass a vector of objects to a function as reference
So do that:
void calculate(vector<Example> &obj) {
for(int i = 0; i < obj.size(); i++) {
obj[i].z = obj[i].x * obj[i].y;
}
}
int main() {
vector<Example> obj;
// put some values into it...
calculate(obj);
}

I believe you wanted your function to be
void calculate(vector<Example> &obj, int M)
and not
void calculate(Example &obj, int M)

obj[i]
'obj' isn't an array.
You need to declare it as:
void calculate(Example* obj, int M)
And rather
void calculate(vector<Example>& v)

Related

How to pass object array to a function?

class department
{
void max() ***HOW TO PASS ARRAY OF OBJECT HERE , WHAT PARAMETERS SHOULD I PASS***
{
}
};
class B : public department {
};
int main()
{
B a[10];
// a.max(a,n); ***HOW TO CALL THIS max FUNCTION***
return 0;
}
I want to pass the array of object a[10] to the max function. How do I call it and pass it?
I don't want to do it like this:
for(i = 0; i < n; i++)
{
a[i].max
}
You implemented max() as a non-static method of department, so you need a department object to call it on, like each B object in your array, eg:
for(int i = 0; i < 10; ++i)
{
a[i].max();
}
If this is not what you want, then max() needs to be taken out of department, or at least made to be static instead. Either way, you will have to change its input parameters to accept the array.
Try something more like this instead:
class department
{
public:
static void max(department *depts, int count)
{
//...
}
};
class B : public department {
};
int main()
{
B a[10];
department::max(a, 10);
return 0;
}
Online Demo
Alternatively:
class department {
};
class B : public department {
};
void max(department *depts, int count)
{
//...
}
int main()
{
B a[10];
max(a, 10);
return 0;
}
Online Demo
How to pass object array to a function?
The parameter of a function cannot be an array in C++. A parameter can be a reference to an array. Alternatively, it is common to pass iterator pointing to an element of an array. Object pointer is an iterator for an array.
department::max() is a non-static member function. It has empty parameter list, so it accepts no arguments at all, except for the implicit class instance that is used as the left hand operand of a member access operator. Since this function accepts no reference to array parameter nor a pointer parameter, there's no way to pass an array as an argument.
Here is an example of a function that does accept a reference to an array as a parameter, and of how to call such function:
void max(B (&arr)[10]);
int main()
{
B a[10];
max(a);
}

Difficulty in passing function pointer of a class member function

In trying to implement a suggested answer here in my own context, I am running into a compilation error.
Consider code:
#include <iostream>
class SIMPLE {
public:
SIMPLE() { for (int i = 0; i < 5; i++) val[i] = 5; };
int retval(int index) { return val[index]; }
private:
int val[5];
};
void print_array_of_length5(int (*fnptr)(int index)){
for (int i = 0; i < 5; i++)
printf("%d ", fnptr(i));
}
int global_array[5] = { 0, 1, 2, 3, 4 };
int global_function(int index){
return global_array[index];
}
int main(){
print_array_of_length5(&global_function);//Works fine.
int (SIMPLE::*p)(int) = &SIMPLE::retval;//Following method suggested in the answer above
class SIMPLE smpl;
print_array_of_length5(smpl.*p);//Compile error: a pointer to a bound function may only be used to call the function
}
The function works when supplied with the address of a global function. It does not work when passed smpl.*p analogous to the method suggested. How should one fix this error?
You need another overload for print_array_of_length5 in order to pass a member function pointer:
template<typename T>
void print_array_of_length5(int (T::*fnptr)(int index), T& obj)
{
for(int i = 0; i < 5; ++i)
{
printf("%d ", (obj.*fnptr)(i));
}
}
int main()
{
SIMPLE smpl;
print_array_of_length5(&SIMPLE::retval, smpl);
}
You can't pass a non-static member function pointer as a regular function pointer. Member functions have access to the this pointer, and the way they get that is via an invisible implicit function parameter. You need to have the object on which to call the function, and the function itself, be bound together, which a function pointer simply can't do.
What we can do is make print_array_of_length5 a function template, and allow it to take any type of callable. That would give you something like this:
template <typename Function>
void print_array_of_length5(Function func){
for (int i = 0; i < 5; i++)
printf("%d ", func(i));
}
To call it with a non-static member function, you can use a lambda expression, or std::bind(), like this:
SIMPLE smpl;
print_array_of_length5([&smpl](int foo){ return smpl.retval(foo); });
using namespace std::placeholders;
SIMPLE smpl;
auto func = std::bind(&SIMPLE::retval, &smpl, _1);
print_array_of_length5(func);

Debugging a C++ code

I am not able to understand what is being returned from function in following code (pointer or value) .
#include<iostream>
using namespace std;
class safearay
{
int a[10];
public:
int& operator [](int n)
{
if(n<0 || n>5 )
{
cout<<"Exceeded bounds"<<endl;
}
return a[n];
}
};
int main()
{
safearay sa1;
for (int j=0;j<10;j++)
{
sa1[j]=j*j;
}
for (int j=0;j<10;j++)
{
int u=sa1[j];
cout<<u<<endl;
}
}
Please explain
int& operator [](int n)
returns a reference to an int.
Essentially, you can use it as int, but changes will affect a[n] in the class too (because it's returned). It's like a pointer without all the *, except you can't change the address where it points to.
Pay attention that in your code you do this:
safearay sa1;
sa1[j]=j*j;
Normally you cannot access the object values like this. The method you're asking about is the operator overload method, that defines what whould the object do on such an access.
int& operator [](int n)
{
if(n<0 || n>5 )
{
cout<<"Exceeded bounds"<<endl<<;
}
return a[n];
}
means
return the reference to the value in the n'th place of the array a in object safearay if n is in
range
The return value is passed by reference, therefore you can assign to it and the change will be in a[i]
You can read more about operator overload here
More about passing values by reference here

how to know the size of the array while initializing an object using this array?

the question says: define a container (possibly a template) of action objects (will be named Runner). Action Objects (AO) are objects that perform a user supplied function. The idea is that once an action container is loaded with AOs it can be asked to run or execute them. The results of the execution are returned in a Results array. example:
AO a1(mul, x, x); //if run method is called it returns x*x
AO a2(add, y, 1); //if run method is called it returns y+1
AO a3(print, s); //if run method is called it prints s on cout
Runner<AO> r = {a1,a2,a3};
so now int the runner class how should I implement a constructor that takes the constant array and knows it size
template<typename a>
class runner{
a* m;
int size;
public:
runner(const a x[]){
//how to know the size of x[] to initialize m=new a[size] and then fill it with a1,a2,a3 ??
}
An array can not know it's size and thus you should pass it as an argument to the constructor.
Even simpler: Use std::vector. With the handy std::initializer_list you can keep initializing your objects with the brace initializers {}. Here an example:
#include <iostream>
#include <vector>
#include <initializer_list>
template<typename a>
class runner{
private:
std::vector<a> objects;
public:
runner(std::initializer_list<a> init) {
objects.insert(objects.end(), init.begin(), init.end());
}
void iterate() {
for(auto obj : objects)
std::cout << obj << std::endl;
}
};
int main() {
//As template type I've chosen int, you can choose your own class AO aswell
//This calls the constructor with the std::initializer_list
runner<int> test = {1,2,3,4,7,0};
test.iterate();
return 0;
}
What u can do is push all the objects in a vector and then pass it in Ctor.
Follow these Steps :
Include:
#include<vector>
In main():
Declare objects of class AO and push them to vector<AO> x
AO a1(mul, x, x); //if run method is called it returns x*x
AO a2(add, y, 1); //if run method is called it returns y+1
AO a3(print, s);
vector<AO> x;
x.push_back(a1);
x.push_back(a2);
x.push_back(a3);
Runner<AO> r(x);
Modify the template class
class Runner{
a* m;
int size;
public:
Runner(vector<a> x)
{
m = new a[x.size()];
for (int i = 0; i < x.size(); i++)
{
m[i] = x.at(i);
}
}
};
Hope this is actually what u want

2D matrix and overloading operator() / ugly syntax

I'm using a 2D matrix in one of my projects. It's something like it is suggested at C++ FAQ Lite.
The neat thing is that you can use it like this:
int main()
{
Matrix m(10,10);
m(5,8) = 106.15;
std::cout << m(5,8);
...
}
Now, I have a graph composed of vertices and each vertex has a public (just for simplicity of the example) pointer to 2D matrix like above. Now I do have a pretty ugly syntax to access it.
(*sampleVertex.some2DTable)(0,0) = 0; //bad
sampleVertex.some2DTable->operator()(0,0) = 0; //even worse...
Probably I'm missing some syntactic sugar here due to my inexperience with operator overloading. Is there a better solution?
Consider using references instead of pointers (provided, it can't be null and you can initialize in the constructor).
Consider making a getter or an instance of a matrix wrapper class for a vertex that returns a reference to 2D matrix (provided, it can't be null).
sampleVertex.some2DTable()(0,0) = 0;
sampleVertex.some2DTableWrap(0,0) = 0;
However, to me it sounds like a non-issue to justify going through all the trouble.
If you have a pointer to a Matrix, e.g. as a function parameter that you can't make a reference (legacy code, e.g.), you can still make a reference to it (pseudo code):
struct Matrix {
void operator () (int u, int v) {
}
};
int main () {
Matrix *m;
Matrix &r = *m;
r (1,1);
}
You're basically limited to (*sampleVertex.some2DTable)(0,0). Of course, if you don't need reseating, why not store the actual values in the matrix instead?
Alternatively, make the pointer private and make an accessor (note: the following examples assume a matrix of EntryTypes):
Matrix& Vertex::GetTableRef()
{
return *some2DTable;
}
// or
Matrix::EntryType& Vertex::GetTableEntry(int row, int col)
{
return (*some2DTable)(row,col);
}
// way later...
myVertex.GetTableRef()(0,0) = 0;
// or...
myVertex.GetTableEntry(0,0) = 0;
Or, just define an inline function to do this for you if you can't change the class Vertex:
// in some header file
inline Matrix& GetTableRef(Vertex& v)
{
return *v.some2DTable;
}
// or you could do this
inline Matrix::EntryType& GetTableEntry(Vertex& v, int row, int col)
{
return (*v.some2DTable)(row, col);
}
// later...
GetTableRef(myVertex)(0, 0) = 0;
// or
GetTableEntry(myVertex, 0, 0) = 0;
Finally, don't forget that you don't have to use operator overloading. STL collections implement an at() member function, which is checked, as opposed to operator[] which is unchecked. If you don't mind the overhead of bounds checking, or if you just want to be nonstandard, you could implement at() and then just call myVertex.some2DTable->at(0,0), saving a bit of a syntactic headache altogether.
There is no C++ syntactic sugar that will ease the pain of what you describe:
(*sampleVertex.some2DTable)(0,0) = 0; //bad
sampleVertex.some2DTable->operator()(0,0) = 0; //even worse...
In this situation, I would either have the graph return a reference instead of a pointer, or have the matrix define a function which calls the operator():
inline matrixType &Matrix::get( int x, int y ){ return operator()(x,y); }
Then, the syntax isn't quite as ugly for the vertex example:
sampleVertex.some2DTable->get(0,0) = 0;
I would add a function that returns you a ref like rlbond recommends. For a quick fix or if you don't have control over the source of it, i would go with this:
sampleVertex.some2DTable[0](0,0) = 0; // more readable
That's actually equivalent, because the following holds if a is a pointer to a defined class:
*a == *(a + 0) == a[0]
See this long discussion on comp.lang.c++ about that same problem with good answers.
This is the best way without changing your code:
//some2DTable is a pointer to a matrix
(*sampleVertex.some2DTable)(0,0)
You could also instead make some2DTable a reference to a matrix instead of a pointer to a matrix. Then you would have simplified syntax as in your first code sniplet.
//some2DTable is a reference to a matrix instead of a pointer to a matrix
sampleVertex.some2DTable(0,0)
Or you could keep some2DTable a pointer to a reference and simply store a reference variable to it and use that in the context of your code block.
I'd change the way you get hold of "sampleVertex.some2DTable" so it returns a reference.
Either that or create the reference yourself:
Matrix& m = *sampleVertex.some2DTable;
m(1,2) = 3;
I don't know if it's worth the trouble, but you could do:
class MatrixAccessor {
private:
Matrix2D* m_Matrix;
public:
MatrixAccessor(Matrix2D* matrix) : m_matrix(matrix) { }
double& operator()(int i, int j) const { return (*m_Matrix)(i,j); }
Matrix2D* operator->() const { return m_Matrix; }
void operator=(Matrix2D* matrix) { m_Matrix = matrix; }
};
Provided the original operator() returns a reference (as it is in many matrix classes).
Then you provide that MatrixAccessor in your vertex class:
class Vertex {
Matrix2D* myMatrix;
public:
MatrixAccessor matrix;
Vertex(Matrix2D *theMatrix) : myMatrix(theMatrix), matrix(theMatrix) { }
};
Then you can write:
Vertex v;
v.matrix(1,0) = 13;
v.matrix->SomeOtherMatrixOperation();
EDIT
I added const keywords (thanks to #phresnel for bringing up the topic) in order to make the solution semantically equivalent to a solution only presenting a public Matrix2D-pointer.
An advantage of this solution is that constness could be transferred to the matrix object by adding two non-const versions of the operator()() and operator->() (i.e. the matrix cannot be modified on const vertices) and changing the const ones to return a const double& and const Matrix2D* respectively.
That would not be possible when using a public pointer to the matrix object.
You could implement Matrix::operator (int,int) by calling a member function and use that one directly when dealing with pointers.
class Matrix
{
public:
float ElementAt( int i, int j ) const { /*implement me*/ }
float operator() ( int i, int j ) const { return ElementAt( i, j ); }
...
};
void Foo(const Matix* const p)
{
float value = p->ElementAt( i, j );
...
}
void Bar(const Matrix& m)
{
float value = m(i,j);
}