Pages: [1]   Go Down
Author Topic: [Solved] Pointer to class instances  (Read 835 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

I'm actually a bit stuck. I need to have a pointer storing an instance of a derived class, but I can't figure out how to do so. Here some code followed by the error message which might help:

RootClass.h
Code:
#ifndef ROOT_H
#define ROOT_H

#include <WProgram.h>

class RootClass {
  public:
    RootClass();
    unsigned char currentValue;
    unsigned char valueCount;
};

#endif

RootClass.cpp
Code:
#include "RootClass.h"

RootClass::RootClass() {
  currentValue = 0;
  valueCount = 4; // some default value
}

Derived.h
Code:
#ifndef DERIVED_H
#define DERIVED_H

#include "RootClass.h"
#include <WProgram.h>

class Derived : public RootClass {
  public:
    Derived();
};

#endif

Derived.cpp
Code:
#include "Derived.h"

Derived::Derived() : RootClass::RootClass() {
  currentValue = 0;
  valueCount = 5; // will overwrite the default value (actually works)
}

sample.ino
Code:
#include "RootClass.h"
#include "Derived.h"

Derived a;
Derived b;

RootClass* current; // this is supposed to point to an instance of Derived, changing while the program is running

void setup() {
   Derived a();
   Derived b();

   current = &a; // FAILS: cannot convert 'Derived (*)()' to 'RootClass*' in assignment
}

// ...

What am I missing here?

EDIT:
Corrected name of constructor of Derived class.
Added [solved] to subject. :-)
« Last Edit: August 07, 2012, 02:15:00 pm by sg80 » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49092
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
class DerivedClass : public RootClass {
  public:
    RootClass();
};
Why is the DerivedClass constructor called RootClass?

Code:
   Derived a();
   Derived b();
This is NOT how to create instances of the DerivedClass class (or the Derived class, for that matter). Loose the ();

Quote
What am I missing here?
You may need a cast, but, as the code posted won't even compile, its hard to say.
Logged

Des Moines, WA - USA
Offline Offline
God Member
*****
Karma: 25
Posts: 779
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A valid pointer 'current' to instance 'a' once 'setup' is exited and the stack unwinds!

EDIT: An answer to the question: "What am I missing here?"
« Last Edit: August 07, 2012, 01:28:00 pm by lloyddean » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you very much! That already helped a lot! Now I've got it working with this code:

Code:
#include "RootClass.h"
#include "Derived.h"

Derived a;
Derived b;

RootClass* current; // this is supposed to point to an instance of Derived, changing while the program is running

void setup() {
   Derived a;
   Derived b;
}

void loop() {
   current = &a;
   Serial.println(String(current->valueCount));
}

// ...

Two questions:
  • As my constructors might need to have some parameters later on, how am I going to pass them (since I need to omit the '()')?
  • Why can't I set the pointer in the setup-routine (where it might be well placed)?
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Two questions:
  • As my constructors might need to have some parameters later on, how am I going to pass them (since I need to omit the '()')?
  • Why can't I set the pointer in the setup-routine (where it might be well placed)?

1. You only omit the parentheses when there are no arguments. Otherwise:
Code:
myclass bob();
it looks like a function declaration called bob that takes no arguments and returns a myclass. On the other hand
Code:
myclass bob(3);
could not be a declaration because there need to be type names inside the parentheses when declaring a function.


2. You can, as long as you don't use it before it's set.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49092
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
    Why can't I set the pointer in the setup-routine (where it might be well placed)?
Because the thing you are pointing to is a local variable that goes away (and gets deleted) when it goes out of scope. Then, you are left with a pointer that does not have the behavior you expect, since the place where ti points to no longer contains an instance of the class that you expect it to have.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Why can't I set the pointer in the setup-routine (where it might be well placed)?

2. You can, as long as you don't use it before it's set.

Which would happen - if I understand you right - because the first loop-call happens before the setup? I would never have guessed so. (?)
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Why can't I set the pointer in the setup-routine (where it might be well placed)?

2. You can, as long as you don't use it before it's set.

Which would happen - if I understand you right - because the first loop-call happens before the setup? I would never have guessed so. (?)

No, it doesn't. Sorry I misunderstood why you were asking -- PaulS' answer is correct.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah, now I understand! I've distinguished between the declaration and the construction - which was not correct. It works when I declare AND construct (in one step) the objects globally:

Code:
Derived a;
Derived b;
RootClass * current;

void setup() {
   current = &a
}

void loop() {
   Serial.println(String(current->valueCount));
   delay(200);
   current = &b;
   Serial.println(String(current->valueCount));
   delay(200);
}

...works fine.

THANKS again! :-)
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49092
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
...works fine.
But doesn't prove anything. If you changed the valueCount field of a and b (by passing a value to the constructor or in setup), and saw that current->valueCount did indeed print differently as you change which object you point to, then you would have proven something.

Code:
  Serial.println(String(current->valueCount));
Don't make me come over there and slap you. There is absolutely no need to convert a char to a String so that the Serial.print() method can extract the char from the String to print it. A monumental waste of resources.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, in the actual program (not the example I posted) the proof has been made; but yes, I'm aware that the example is insufficient concerning that.

To justify myself for the waste of resources, I again need to refer to the difference between the example and my actual program, where not a Serial.print is called, but a function which expects a String. I apologize for that smiley
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49092
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
but a function which expects a String.
Your function? Rewrite to accept a char *, and get rid of the String class. There is a major bug in the free() function that String uses that can corrupt your program much sooner than was originally thought, considering how many times String calls malloc() and free() (to increase the size of a String by one char).

Quote
I apologize for that
Don't apologize. Change it.   smiley-cool
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Uh oh, you were right, I'm running into memory-problems due to the usage of the String-class.

Is that a bug to be fixed in near future or will I need to find a different solution by myself? Where can I get more information about that issue? I could only find some 2 or 3 year old information about something similar (which seems to be fixed meanwhile).

I'm not very used to handling strings using char-arrays or char*s. Is there any good tutorial out there?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49092
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Where can I get more information about that issue?
http://arduino.cc/forum/index.php/topic,115552.0.html

Quote
Is that a bug to be fixed in near future
Not likely.

Quote
or will I need to find a different solution by myself?
Follow that thread. There is a fix available, but I'd still avoid the use of String.

Quote
I'm not very used to handling strings using char-arrays or char*s. Is there any good tutorial out there?
Probably. But, it isn't rocket science. Break the problem down into stages. Collect data, and store it in an array. When that works, move onto to parsing/searching the stored data. Keep in mind the need to reset the array and index at appropriate points.
Logged

Pages: [1]   Go Up
Jump to: