0

My test are based on the blog of http://arduinoetcetera.blogspot.be/2011/01/classes-within-classes-initialiser.html.

Because I would like to use this idea, I tried with a simple idea, after the instance is created just update a value.

But for some reason, the code compiles perfectly and there seems to be no error with the update method, but it DOES NOT UPDATE the variable.

But my output on the serial monitor show that the number (volatile int) doesn't update.

Object of class First has value - Number: 6
Object of class Second has value - Number: 13
Object of class Second has value - Double: 26
Object of class Second has value - Update: [0] - 20  // <--
- - 
Object of class First has value - Number: 6
Object of class Second has value - Number: 13        // <--
Object of class Second has value - Double: 26
Object of class Second has value - Update: [1] - 70
- - 
Object of class First has value - Number: 6
Object of class Second has value - Number: 13

code - MAIN : First thing(6, 13); [edited on request of @Mark Smith]

#include "First.h"
First thing(6, 13);
...
int newValue;
...
int ledPins[] = {
  20, 70, 45, 68, 543, 321
}; // an array of pin numbers to which LEDs are attached
int pinCount = 6; // the number of pins (i.e. the length of the array)
bool plus=true;
int index=-1;
void loop() {
  Serial.print("Object of class First has value - Number: ");
  Serial.println(thing.Number());
  Serial.println();
  Serial.print("Object of class Second has value - Number: ");
  Serial.println(thing.getSecond().Number());
  Serial.print("Object of class Second has value - Double: ");
  Serial.println(thing.getSecond().Double());
  ...  
  Serial.print("Object of class Second has value - Update: [");
  if ( plus && index == (pinCount-1) ) {
    plus=!plus;
  }
  if ( !plus && index == 0 ) {
    plus=!plus;
  }
  // change + <--> -
  (plus) ? index++ : index--;
  newValue=ledPins[index];
  Serial.print(index,DEC);
  Serial.print("] - ");
  Serial.println(newValue, DEC);
  thing.getSecond().Update(newValue);
  Serial.println("- - ");

code - FIRST

#include "First.h" 
...
First::First(int firstNumber, int secondNumber) : widget(secondNumber) {
  itsNumber = firstNumber;
}
int First::Number() {
  return itsNumber;
}
Second First::getSecond() {
  return widget;
}

code - SECOND : void Second::Update(int newNumber)

#include "Second.h"
...
volatile int itsNumber;
Second::Second(int newNumber) {
  itsNumber = newNumber;
}
void Second::Update(int newNumber) {
  itsNumber = newNumber;
}
int Second::Number() {
  return itsNumber;
}
int Second::Double() {
  return itsNumber*2;
}

For the complete code https://github.com/droopy4u/ARDUINO - https://github.com/droopy4u/ARDUINO/tree/master/ClassWithClasses -

2
  • 1
    Could you post the actual code please? The part you've posted doesn't show the problem part. It's not good to rely on external links because they might disappear, and in your case it's not obvious (enough that I can be bothered to work out) which of the two very similar sets of files in your git repo you're using. Thanks.
    – Mark Smith
    Commented Dec 16, 2016 at 16:32
  • 1
    This isn't an Arduino specific question, its general C/C++ BUT it is quite an important problem that lots of novice programmers have so I don't think it should be moved. Commented Dec 16, 2016 at 16:48

2 Answers 2

0

Even without the real code, I think the problem is with the function First::Second().

You need to understand what happens in C++ when values are passed as parameters. The are passed by value by default, this means a COPY of the value is passed into the function, you can modify the parameter all you like but when you return those changes are lost.

There are two exceptions to this, the first is pointers. When you pass in a pointer you can modify what is pointed to but you still can't modify the pointer, because that is a copy. If you want to modify the pointer then you need a pointer to a pointer int** ptr_to_ptr.

The other exception is a reference. In this case the function can modify the parent function's variable. This is more efficient in terms of memory.

So you have:

int AddOne(int value) {++value; return value};   // 5 == AddOne(5);
int AddOne (int value) {return value+1};         // 6 == AddOne(5); - doesn't modify the parameter.
int AddOne(int* pValue) {(*value)+1; return *value;}//6 == AddOne(5); - Pointer 
int AddOne(int& value){++value; return value;}   // 6 == AddOne(5); - Referance
int AddOne(const int& value){++value; return value;} // Compiler error, modifying const value.

So why it is First::Second() causing the problem? Well the same rules apply to return values as to parameters and you are returning a copy of the value widget so you then modify that copy and then dispose of it. So this is what you need to fix the problem.

Second& First::getSecond()
{
    return widget;
}

EDIT : Its not clear in the preceding text but you don't need getSecond() to return a reference if you are not altering the value of widget so getDouble() will return the expected value because it is working form a copy of the original and not storing any changes. However update() will not work as expected because the result of getSecond() goes out of scope (gets disposed of) once the call is complete. The changes its made are not save to the original because it is working on a copy.

9
  • PART1 Thank you very much for response ... first I was thinking and tried the same thing but then in the Class with the variable, but most probably I did something wrong, because of the compiler errors. But I created a First.cpp and a First.h file - library. - so is it then not an instance? I try to understand it ... but find it hard to solve the problem.
    – kris
    Commented Dec 17, 2016 at 8:46
  • PART2 Tried your suggestion by Second& First::getSecond() as well Second &First::getSecond() -> prototype ... does not match any in class 'First'. I'm a beginner, but if I call the method thing.getSecond().Double() then it returns the correct data ` int Second::Double(){ return itsNumber*2; }` as 26. But it seems that the update is not working well, do you maybe have an other suggestion?
    – kris
    Commented Dec 17, 2016 at 8:46
  • ... thanks for your quick response and effort Because I have not enough reputation I'm not able to vote on your answer. Even not enough privilege to edit my own comment. Thank you very much.
    – kris
    Commented Dec 17, 2016 at 9:47
  • The position of the space doesn't matter in this case, but I prefer Second& First::getSecond() because it makes it a bit clearer that it is Second you are referencing. The error prototype ... does not match any in class 'First' means you need to change it in the .h and the .cpp file. Commented Dec 18, 2016 at 15:11
  • 1
    Now it is clear ... just an other COPY of the widget. Thank you very much ... An other question ... were you may be know the answer to let (the two) classes communicate with each other ... what is the best way to do it. Event handlers ... or ... what are you recommendations?
    – kris
    Commented Dec 18, 2016 at 15:42
0

@MATT, with trying to get the address of variable via

    const long SERIAL_SPEED=38400;//baud rate of the serial communication

//global variable
    int a = 15;
    int *b=a;

void infoVar(){
    Serial.print("\n\n");
    Serial.print(" a -  ");  Serial.println(a, DEC );
    Serial.print("*b -  ");  Serial.println(*b, DEC );  // dereferencing
    Serial.print("\n");

    Serial.print("int  b - ");  Serial.println( (int) b, DEC );   // ???
    // This is the content of the pointer variable b
    Serial.print("int &b - ");  Serial.println( (int) &b, DEC );  // address of memory location where b is stored
    Serial.print("int &a - ");  Serial.println( (int) &a, DEC );  // address of memory location where a is stored 
}

void setup() {
  // put your setup code here, to run once:
    Serial.begin(SERIAL_SPEED);      // open the serial port at SERIAL_SPEED bps:

    Serial.println("Started : ### reference_pointer ###\n\n");


// *** :  when uncomment next line : the value b = 123
//b=123

    *b=a;
    infoVar();

    a=235;
    *b=a;
    infoVar();

    a=1928;
    *b=a;
    infoVar();

    }

void loop() {
  // put your main code here, to run repeatedly:
}

OUTPUT

 a -  15
*b -  15

int  b – 15
        // don't understand here that it is 15
            //thought that is would be the the address of the variable 'a'
            // it seems that it keeps the first initiated value??? ***
int &b - 676
int &a - 256


 a -  235
*b -  235

int  b - 15
int &b - 676
int &a - 256


 a -  1928
*b -  1928

int  b - 15
int &b - 676
int &a - 256

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.