unable to change member value with method - c++

I have an int member named size within my blob class whose value I am attempting to change within a method. Initially, I tried...
void blob::make_union(blob parent_blob){
parent=&parent_blob;
parent_blob.size = parent_size
}
Then I tried making a function whose sole purpose was to change the size value. Its worth noting that it changes the values within the function as verified by some cout statements.
int blob::change_size(int dat_size){
size=size+dat_size;
return this.size;
}
after making the new method change my other method
'void blob::make_union(blob parent_blob){
parent=&parent_blob;
int temp = size;
parent_blob.size = parent_blob.change_size(temp);
}'
still no dice. The following within main function does work.
if (charmatrix[m-1][n-1]==charmatrix[m][n]){
blobmatrix[m][n].make_union(blobmatrix[m-1][n-1]);
blobmatrix[m-1][n-1].size=blobmatrix[m-1][n-1].size + blobmatrix[m][n].size;
What am I doing wrong?

You are passing your blob class by value: you are making a copy of your blob object, and that is what the function change_size is working with.
void increment_number(int i) { ++i; }
void increment_number_ref(int& i) { ++i; }
int main()
{
int n = 6;
// This takes a copy of the number, and increments that number, not the one passed in!
increment_number(n);
// n == 6
// This passed our object by reference. No copy is made, so the function works with the correct object.
increment_number_ref(n);
// n == 7
return 0;
}
You need to pass your blob by reference (or as a pointer) if you wish to modify that object's value: see above.

In languages that have pass by reference and pass by value - if you have a situation where you make a change, and then suddenly the change is 'gone', you're almost certainly passing a copy vs a reference.
Try changing the prototype to pass in the blob by reference.

Related

Calling member function from non memebr function besides main? [duplicate]

In the following call-by-value example, I cannot understand why this code is not changing the value of the 5 to a 6.
Line 11 calls the function changeValue which has the value 6, so I would have thought 6 should be output, however 5 is still output?
#include <iostream>
using namespace std;
void changeValue(int value);
int main()
{
int value = 5;
changeValue(value);
cout << "The value is : " << value << "." << endl;
return 0;
}
void changeValue(int value)
{
value = 6;
}
// This doesn't change the value from 5 to 6. 5 is output?
When you pass a function argument by value a copy of the object gets passed to the function and not the original object.Unless you specify explicitly arguments to functions are always passed by value in C/C++.
Your function:
void changeValue(int value)
receives the argument by value, in short a copy of value in main() is created and passed to the function, the function operates on that value and not the value in main().
If you want to modify the original then you need to use pass by reference.
void changeValue(int &value)
Now a reference(alias) to the original value is passed to the function and function operates on it, thus reflecting back the changes in main().
The value of value isn't changing because your int that you pass to the function is being copied into the stack frame of the function, then it's being changed, and when the function exits the copy is destroyed. The original in main's stackframe has not changed, since it was copied to the changeValue.
If you want to change it, you should pass a reference to an int, like so void changeValue(int& value), which says that the value isn't copied into the function, but merely an alias to the original is passed.
The behavior being observed currently is because passing by value means a copy of value (new integer with value of value) is actually passed to the function.
You have to pass by reference. For that the changeValue function will look like this:
void changeValue(int& value)
Rest of the code will remain the same.
Passing a variable by reference means the same int value declared in main is passed to the changeValue function.
Alternatively, you can pass a pointer to value to the changeValue function. That will however, require changes to how you call the function also.
int main()
{
int value = 5;
changeValue(&value);
...
return 0;
}
void changeValue(int* value)
{
*value = 6;
}
I'm including this answer as another way to think about writing functions and passing parameters by value.
You could also have written this code in the following way. That is pass the parameter by value, modify the local copy in the function, which does not alter the original value, and return the altered value.
int changeValue(int val)
{
val = 6;
return val;
}
int main()
{
int value = 5;
value = changeValue(value);
cout << "The value is : " << value << "." << endl;
return 0;
}
I am not in any way indicating my suggestion for your program is better than passing by reference. Instead, it is just the way learning a functional programming language (Clojure) is affecting the way I think.
Also, in languages like Python, you cannot modify a scalar parameter. You can only return a new value. So my answer is more of an exercise in thinking about things differently in C/C++.
AND:
the copy is assigned 6, but the change is not returned.
you need some reference or pointer if you want to change the value:
try using a method signature like:
void changeValue(int& value)
that will probably do what you expected
This is because the change in the changeValue () function is local. When you can changeValue (value) the contents of the variable value in main is copied in the formal argument named value (same name) of the function. Same name does not mean that the both are same. The value you are accessing inside the function is a copy of the value you had in the main.
To change you either need to pass it by reference or a pointer
void changeValue (int *val)
{
*val = 6;
}
call with changeValue (&value) in main
This works because the address of the variable value in main is passed and this address value is copied into val of the function. By doing *val we can get the contents of the address which was copied into val, which in actually the contents of value in main.
OR
void changeValue (int &val)
{
val = 6;
}

Changing values of class instances in a function [duplicate]

This question already has answers here:
Pass by reference and value in C++
(5 answers)
Closed 5 years ago.
I wrote the folloing code to test how to change values of class object in a function.
using namespace std;
class test{
public:
int a;
};
void runer(test testXX){
testXX.a=10;
}
int main()
{
test test1;
test1.a=5;
runer(test1);
cout<<test1.a;
return 0;
}
When I run the following code the output is 5 and not 10. Is it because I can't change the values of class instances, like I can't change the values of array members without using pointers? I would be grateful if someone could clarify that!
void runer(test testXX){
testXX.a=10;
}
Takes a full copy of the type test, so it is modified in the function, but a different instance to the one in main.
Parameters in C++ are sent by value. The simplest example which makes sense is
int function( int value ) {
for( ; value > 0 ; value-- ){
cout << "Hello\n";
}
}
int main( int , char ** ){
int value = 10;
function( value ); // display 10 things
function( value ); // display 10 things again (not modified).
function( 5 ); // also not making sense, if parameter is modified.
}
To allow objects to be modified, they need to be sent as references, or pointers. This allows the value of the item to be changed. The literal 5 can not be sent to a function expecting a reference.
void runer(test & testXX){
testXX.a=10;
}
Now the same object is sent from main to runner, and modifications are done to the single object.
You are passing the argument to the function by value, so it gets a local copy that only lives as long as the scope of the function.
If you want the function to be able to modify the original object that you pass in, then pass it by non-const reference void runer(test& testXX) .
Your code makes a call by value. Hence, the change doesn't appear in the actual object. To change the value of the attribute of the object you need to make a call by reference.
void runer(test &t){
t.a = 10;
}

function doesn't change object attributes in c++

I am totally new to c++ and thought it would be good practice to write a program which solved a given liter puzzle (you have 2 containers with capacities of 3 and 5 liters, can you obtain 4 liters? etc.)
I wrote a class for a given container and a function which was intended to 'pour' the contents of one container into another. The function doesn't change the value of the contents of any object however, despite the entire class being public. I'm not sure what I'm doing wrong.
Here is my code:
#include <iostream>
using namespace std;
class Container {
public:
int quantity; //quantity of water in container
int size; //max amt of water
};
void pour(Container a, Container b) {
int differential = b.size - b.quantity;
if (a.quantity <= differential) {
b.quantity = a.quantity + b.quantity;
a.quantity = 0;
}
else if (a.quantity > differential) {
b.quantity = b.quantity - differential;
a.quantity = a.quantity - differential;
}
};
int main() {
Container bottle1;
bottle1.quantity = 5;
bottle1.size = 6;
Container bottle2;
bottle2.quantity = 0;
bottle2.size = 2;
pour(bottle2, bottle1);
cout << bottle1.quantity << ", " << bottle2.quantity << endl;
return 0;
}
I'm sure my mistake is obvious but I can't find an answer anywhere. Any help would be greatly appreciated.
You're passing the Containers as copies. This means that the containers you alter in the pour function are destructed upon function exit.
The solution is to use references:
void pour(Container& a, Container& b)
The & after the type denotes a reference. This means that, instead of copies of a and b being used inside pour, the function gets access to the same a and b as the caller.
This is probably because you're passing the objects by value. You'll want to pass them by reference. You can do this by changing your method header.
Essentially, each instance of Container in the method header should become Container&. The call will not need to be changed.
You can also pass pointers. Your arguments would then become Container *a, and in your call you'd have to add an ampersand (&) before each variable name (e.g. a becomes &a). You'd then also have to change any derefs of the object from periods (.) to arrows (->).
Your method would become:
void pour(Container *a, Container *b) {
int differential = b->size - b->quantity;
if (a->quantity <= differential) {
b->quantity = a->quantity + b->quantity;
a->quantity = 0;
}
else if (a->quantity > differential) {
b->quantity = b->quantity - differential;
a->quantity = a->quantity - differential;
}
};
I mentioned both because in some cases, the designers of a program will adopt the convention that all references are const references. That is, any object passed by reference is not to be modified (which is enforced by using the const keyword before the type name in a method header), and that all other objects are passed by pointer. This makes it more clear, in the function call, whether or not an argument will be modified.
The choice of using a const reference over pass-by-value in that convention is to improve the efficiency of a function call. It is quicker to pass a reference than to make a copy of an object.

Passing integer by reference to a class in c++

I have a thread-class Buffer (own made class), and many derived classes such as BufferTypeA, BufferTypeB...
Since I have to synchronize them in a certain order, I'm giving any of them an integer which represents the order to run certain task. I also have to know inside each thread Buffer which one is next to run the task, so I'm passing every BufferType a reference to an integer which all of them must share and I didn't want to make it Global.
I got lost at any point and I don't see where.
First I create all the BufferTypes from a class where I also define that shared integer as:
int currentThreadOrder;
And when creating the BufferTypes:
int position = 0;
if (NULL == bufferA) {
bufferA = new BufferTypeA(&currentThreadOrder, ++position,
waitCondition);
}
if (NULL == bufferB) {
bufferB = new BufferPos(&currentThreadOrder, ++position,
waitCondition);
}
if (NULL == bufferC) {
bufferC = new BufferRtk(&currentThreadOrder, ++position,
waitCondition);
}
Then, in BufferTypeA header:
class BufferTypeA: public Buffer {
public:
BufferTypeA(int currentThreadOrder,
int threadConnectionOrder = 0,
QWaitCondition *waitCondition = NULL);
//..
}
And in cpp file:
BufferTypeA::BufferTypeA(int currentThreadOrder, int threadConnectionOrder, QWaitCondition *waitCondition):
Buffer(currentThreadOrder, threadConnectionOrder, waitCondition) { }
Now I'll show Buffer header:
class Buffer: public QThread {
public:
Buffer(int &currentThreadOrder,
int threadConnectionOrder = 0,
QWaitCondition *waitCondition = NULL);
//...
protected:
QWaitCondition *waitCondition;
int threadConnectionOrder;
int &currentThreadOrder; // Shared address
}
And finally the cpp:
Buffer::Buffer(int &currentThreadOrder, int threadConnectionOrder, QWaitCondition *waitCondition) {
this->threadConnectionOrder = threadConnectionOrder;
this->waitCondition = waitCondition;
this->currentThreadOrder = currentThreadOrder;
}
And the error I'm getting is error: uninitialized reference member Buffer::currentThreadOrder.
I'm embarrased to ask, because it's going to be a simple problem with pointers and addresses, but I can't see where the problem is, so please help.
When you create a class with a data-member that is a reference, the reference needs to be assigned a value in the constructor initializer list.
References have to be given a value when they are created, they are not pointers. They have to start with a value and that value cannot be changed (while the contents that is pointed to by that value can be changed).
Essentially you can think of a reference as an alias for an existing variable. You can't give a friend a nickname if you don't have a friend :)
RESPONSE TO COMMENT:
You don't "share a reference" between objects. Each object will have its own reference to the same variable. When you "pass by reference" you are telling the compiler that you want the variable in your function to actually be the variable in your outer scope, rather than creating a new variable by value. This means that you only have one variable at one memory location. The reference is just memory in some other place that forwards you to that same memory location.
Think of this as call forwarding... I can have 15 phone numbers in 15 different countries. I can set them all up to forward calls to my cell in the US. So, people are calling me no matter which number they call.
Each of your classes just has another reference to forward the "phone calls" or variable reads/writes to that same memory location. So, you're not sharing a reference between classes, you're making sure that each class HAS a reference to the same underlying memory location.
Back to the metaphore, each class won't have the same phone, but each class' phone will forward to the same number (variable) none-the-less which lets them all set/get the same value in the end.
RESPONSE II:
Here's a simple example to get your head going, it's pretty easy to apply to your classes. I didn't compile it but it should work minus a typo or two possibly.
class A
{
public:
A(int& shared) : m_shared(shared)
{
//No actions needed, initializer list initializes
//reference above. We'll just increment the variable
//so you can see it's shared in main.
m_shared += 7;
}
void DoSomethingWithIt()
{
//Will always reflect value in main no matter which object
//we are talking about.
std::cout << m_shared << std::endl;
}
private:
//Reference variable, must be initialized in
//initializer list of constructor or you'll get the same
//compiler error again.
int& m_shared;
};
int main()
{
int my_shared_integer = 0;
//Create two A instances that share my_shared_integer.
//Both A's will initialize their internal reference to
//my_shared_integer as they will take it into their
//constructors "by reference" (see & in constructor
//signature) and save it in their initializer list.
A myFirstA(my_shared_integer);
A mySecondA(my_shared_integer);
//Prints 14 as both A's incremented it by 7 in constructors.
std::cout << my_shared_integer << std::endl;
}
you pass a pointer int* as 1st argument to BufferTypeA, which expects and int, while you said in your question you meant to use a int&. To do this, the ctor of BufferTypeA should take a int& and initialise it in an initialisation list (i.e. not within the { } part of the ctor) like
class BufferType {
int &Ref;
public:
BufferTypeA(int& ref) : Ref(ref) { /* ... */ }
};
and in your construction of BufferA you must not pass an address, but the reference, i.e.
int counter;
Buffer = new BufferType(counter);
You want code like this:
Buffer::Buffer(
int &currentThreadOrder0,
const int threadConnectionOrder0,
QWaitCondition *const waitCondition0
) :
threadConnectionOrder(threadConnectionOrder0),
waitCondition(waitCondition0),
currentThreadOrder(currentThreadOrder0)
{}
The reason is related to the reason you cannot write
const double pi;
pi = 3.14;
but can write
const double pi = 3.14;
A reference is typically implemented as a constant pointer, to which one cannot assign an address after one has initialized the pointer. Your version of the code assigns, as in the first pi example. My version of the code initializes, as in the second pi example.

C++ parameter is a pointer to a constant object but the updated object is not returned?

I have native C++ class SrcClass containing the following:
std::vector<shotEntry> objectsQueue;
bool getRelatedEntry(const entryToProcess *entriesDeets, int &i) const {
if (i >= (int)objectsQueue.size()) {
i = 0;
return false;}
if (!objectsQueue.size()) return false;
entriesDeets = &(objectsQueue[i++]);
return true;
}
In my client I have:
const entryToProcess *entriesDeets = NULL;
int i = 0;
while (srcObj->getRelatedEntry(entriesDeets, i)) {
When I step through getRelatedEntry the formal parameter, entriesDeets is updated as expected before returning. When it returns the actual parameter of the client is not updated.
This is in some big project I have returned to after two months away. I'm pretty sure the last refactoring I did was to introduce these damnable vectors. It takes ages to compile when I mess with headers. Am I getting confused with the initialize once/ readonly/ const'ness of C#? Can I get away with the client getting a read only native object back?
This is because you are setting the value of the function's parameter. You want:
bool getRelatedEntry(const entryToProcess **entriesDeets, int &i) const {
...
*entriesDeets = &(objectsQueue[i++]);
...
and
srcObj->getRelatedEntry(&entriesDeets, i)
entriesDeets is a local variable inside getRelatedEntry. You only modified the local, you didn't affect the value passed in. You need to pass a reference to pointer or a pointer to pointer.
The pointer is updated, but it is the internal copy inside the function. If you want that change to be visible outside of the function, you should pass a reference:
// v
bool getRelatedEntry(const entryToProcess *&entriesDeets, int &i) const {
Or in C style a double pointer and dereference it internally on every usage:
// v
bool getRelatedEntry(const entryToProcess **entriesDeets, int &i) const {
// ...
*entriesDeets = &(objectsQueue[i++]);