How to Pass Objects to Functions in C++

How to pass object to function in c++?

You can pass by value, by reference or by pointer. Your example is passing by value.

Reference

void show(abc& S)
{
cout<<S.display();
}

Or, better yet since you don't modify it make it int display() const and use:

void show(const abc& S)
{
cout<<S.display();
}

This is normally my "default" choice for passing objects, since it avoids a copy and can't be NULL.

Pointer

void show(abc *S)
{
cout<<S->display();
}

Call using:

show(&a);

Normally I'd only use pointer over reference if I deliberately wanted to allow the pointer to be NULL.

Value

Your original example passes by value. Here you effectively make a local copy of the object you are passing. For large objects that can be slow and it also has the side effect that any changes you make will be made on the copy of the object and not the original. I'd normally only use pass by value where I'm specifically looking to make a local copy.

How to pass objects to functions in C++?

Rules of thumb for C++11:

Pass by value, except when

  1. you do not need ownership of the object and a simple alias will do, in which case you pass by const reference,
  2. you must mutate the object, in which case, use pass by a non-const lvalue reference,
  3. you pass objects of derived classes as base classes, in which case you need to pass by reference. (Use the previous rules to determine whether to pass by const reference or not.)

Passing by pointer is virtually never advised. Optional parameters are best expressed as a std::optional (boost::optional for older std libs), and aliasing is done fine by reference.

C++11's move semantics make passing and returning by value much more attractive even for complex objects.



Rules of thumb for C++03:

Pass arguments by const reference, except when

  1. they are to be changed inside the function and such changes should be reflected outside, in which case you pass by non-const reference
  2. the function should be callable without any argument, in which case you pass by pointer, so that users can pass NULL/0/nullptr instead; apply the previous rule to determine whether you should pass by a pointer to a const argument
  3. they are of built-in types, which can be passed by copy
  4. they are to be changed inside the function and such changes should not be reflected outside, in which case you can pass by copy (an alternative would be to pass according to the previous rules and make a copy inside of the function)

(here, "pass by value" is called "pass by copy", because passing by value always creates a copy in C++03)


There's more to this, but these few beginner's rules will get you quite far.

How to pass objects to functions by reference in C++?

You're getting a linker error, which means that the compiler was able to compile the program but couldn't find the implementation for one of the member functions you wrote. Notice that it's saying that ClassA::Function(Class A&) is the undefined symbol, meaning that the compiler never found an implementation for this function.

So why is that? Well, in other.cpp, you implemented the following:

ReturnType Function (B&) {
...
}

This is a free function named Function, which is not the same as the function ClassA::Function. This means that the compiler doesn't treat it as a member function, so when it compiles your code it never ends up finding ClassA::Function.

To fix this, change Function in the .cpp file so that you explicitly indicate it's a member function:

ReturnType ClassA::Function(B&) {
...
}

That should resolve your error.

How to pass objects as arguments?

You can not access member variables in the main function because they are private.
You can send the first instance to the method as a parameter, then use the class A member variables inside the method.

#include<iostream>
using std::cin;
using std::cout;
using std::endl;

class A
{
int a;
int b;

public:
friend class B;
int enter1()
{
cout<<"enter the value of a and b"<<endl;
cin>>a>>b;
return(a,b);
}
};

class B
{
int c;
int d;
int e;

public:
void average(A obj)
{
float avg;
avg=((obj.a+obj.b+c+d+e)/5);
cout<<"average is "<<avg<<endl;
}

int enter()
{
cout<<"enter the value of c,d,e"<<endl;
cin>>c>>d>>e;
return(c,d,e);
}
};

int main()
{
A obj1;
B obj2;

obj1.enter1();
obj2.enter();
obj2.average(obj1);
return 0;
}

passing object by reference in C++

What seems to be confusing you is the fact that functions that are declared to be pass-by-reference (using the &) aren't called using actual addresses, i.e. &a.

The simple answer is that declaring a function as pass-by-reference:

void foo(int& x);

is all we need. It's then passed by reference automatically.

You now call this function like so:

int y = 5;
foo(y);

and y will be passed by reference.

You could also do it like this (but why would you? The mantra is: Use references when possible, pointers when needed) :

#include <iostream>
using namespace std;

class CDummy {
public:
int isitme (CDummy* param);
};


int CDummy::isitme (CDummy* param)
{
if (param == this) return true;
else return false;
}

int main () {
CDummy a;
CDummy* b = &a; // assigning address of a to b
if ( b->isitme(&a) ) // Called with &a (address of a) instead of a
cout << "yes, &a is b";
return 0;
}

Output:

yes, &a is b

Passing objects into functions within another class c++

Where you go wrong is that at this point:

    void write(int x)
{
dataObject.var = x;
}

there is no dataObject. You are trying to make your classes depend on some global object. First of all you have to decide if you really want this. And if you do, you need a way to ensure that these global objects are declared and instantiated before they get used by the classes.

There are many ways to fix the error, but first you need to be clear about what you want the classes to do and how they should interact with each other.

One example of how you could fix this without global objects:

class class1
{
public:
class1(data& dataObj) : dataRef_(dataObj) {}
void write(int x)
{
dataRef_.var = x;
}
private:
data& dataRef_;
};

Then in the main:

int main()
{
data dataObject;
class1 object1(dataObject);
object1.write(2);
}

C++: Passing objects by value to a member function of the same class

I made a few comments in your original code to explain why real and imaginary are affect below. (Look for //MABVT)

In addition:
I will provide another useful example for you to progress further!

REVIEW

class complex {
private:
int real;
int imaginary;

public:
/* Using member initializers to assign values to members */
complex()
: real(0)
, imaginary(0)
{}

void readData(int x, int y);

void printData();

// MABVT: You provide two complex numbers which you want to add
// together!
void addNumbers(complex, complex);
};

void complex::readData(int x, int y)
{
real = x;
imaginary = y;
}

void complex::printData()
{
cout << real << "+" << imaginary << "i" << endl;
}

void complex::addNumbers(complex c1, complex c2)
{
// MABVT: Use c1.component and c2.component, add them up and store them
// in this class' instance.
real = c1.real + c2.real;
imaginary = c1.imaginary + c2.imaginary;

// MABVT: c3.real and c3.imaginary are affected at this exact location
// since you overwrite the values with the addition-results.
// Since the function addNumbers(complex, complex) is invoked
// on the complex instance 'c3', real and imaginary of c3 are
// known in this context, and consequently you can use them.
//
// To attach to your statement that the c3 instance's pointer is
// implicitly passed:
// Yes it is passed as the first parameter invisibly as
// 'complex* this'
//
// So you could also write:
// this->real = c1.real + c2.real; (see the use of this?)
}

int main(void)
{
complex c1, c2, c3;
c1.readData(-5,17);
c2.readData(11,7);
c3.addNumbers(c1,c2);
c3.printData();

return 0;
}

ALTERNATIVE

// Example program
#include <iostream>
#include <string>

class Complex { // Give class names capital first letter
private:
int m_real; // Just a recommendation: I'd like to be able to distinguish parameter for member in the identifier already!
int m_imaginary; // Just a recommendation: I'd like to be able to distinguish parameter for member in the identifier already!

public:
/* Using member initializers to assign values to members */
inline Complex() // Inline it, if you define this class in a header and reuse it multiple times...
: m_real(0)
, m_imaginary(0)
{}

// Provide initializing constructor to be able to construct
// a complex number quickly. Replaces your readData(...);
inline Complex(
int inRealPart,
int inImaginaryPart)
: m_real(inRealPart)
, m_imaginary(inImaginaryPart)
{}

// Getters to read the values
inline int real() const { return m_real; }
inline int imaginary() const { return m_imaginary; }

void printData();

// Local assignment-add operator to add another complex
// to this specific instance of complex and modify the internal
// values. Basically what you did as the second part of addNumbers.
Complex& operator+=(const Complex& r);
};

void Complex::printData()
{
std::cout << m_real << "+" << m_imaginary << "i" << std::endl;
}

// Member add-assign operator definition adding this instance and another instance 'r' by adding up the values and storing them in the instance this operator is called on.
Complex& Complex::operator +=(const Complex& r)
{
std::cout << "Local" << std::endl;

this->m_real += r.real();
this->m_imaginary += r.imaginary();

return *this;
}

// Static global operator+ definition, taking two values and creating a
// third, NEW one initialized with the results.
// This was the first part of addNumbers
static Complex operator+(const Complex& l, const Complex& r) {
std::cout << "Static Global" << std::endl;

return Complex(
(l.real() + r.real()),
(l.imaginary() + r.imaginary())
);
}

int main(void)
{
// Same as before
Complex c1(-5, 17);
Complex c2(11, 7);
Complex c3(1, 2);

// Test output
c1.printData();
c2.printData();
c3.printData();

std::cout << std::endl;

Complex c3 = (c1 + c2); // Calls static global and c3 is overwritten with the result. Exactly like your addNumbers call
c1 += c2; // instance local, will change c1's internal values ( see print out below )
Complex c5 = ::operator+(c1, c2); // Static global, c5 is initialized with the result. Exactly like your addNumbers call

std::cout << std::endl;

c1.printData();
c2.printData();
c3.printData();
c5.printData();

return 0;
}

This should be quite much for you as a beginner.

Some explanation

Static global vs. local operator overloads

Reading on the topic: http://en.cppreference.com/w/cpp/language/operators

All the operators you use (+, -, *, /, %, +=, -=, ...) are just functions, which are predefined for primitive types and provided by libstd for STD types.

You can override/define them though.

I did that in two ways:

Static global operator+:

Accepts two arbitrary Complex instances and adds their components.
Finally a NEW instance is created and initialized with the results.

Basically this is just a static function, which is linked to "+" by
the compiler.

And:

Local member operator+=:

Accepts another instance of Complex and adds its component values to
the component values of the instance the operator is called on: `l
+= r -> Called on l, whose values will be modified by adding the values of r'

All op-assignment operators (+=, -=, *=, /=, etc...) must be defined
within the class and can neither be global, nor static.

const Type&

Reading with much more info on const: https://www.cprogramming.com/tutorial/const_correctness.html

Const reference to instances of whatever type will ensure two things for you:

  1. &: You only copy the address, but this way you function could change all public values or call most functions.
  2. const: The instance is not modifyable and nothing can be changed

In combination that means: You don't have to copy the instance (pass-by-value), but provide it's address reference only (pass-by-reference). Usually that enhances performance, especially once you pass around large and complex objects.

Does C++ pass objects by value or reference?

Arguments are passed by value, unless the function signature specifies otherwise:

  • in void foo(type arg), arg is passed by value regardless of whether type is a simple type, a pointer type or a class type,
  • in void foo(type& arg), arg is passed by reference.

In case of arrays, the value that is passed is a pointer to the first element of the array. If you know the size of the array at compile time, you can pass an array by reference as well: void foo(type (&arg)[10]).



Related Topics



Leave a reply



Submit