Can a class to contain an array of classes?

I'm trying to encapsulate some code in a class, but the class object contains 4 very similar things that I would normally make another class.

Lets call the outer class Hand, and the desired other class Finger. Normally I'd put the Fingers in a collection within Hand so I could refer to things like myHand.itsFinger(0).func();

I'm still trawling through Google for examples, but either I haven't found the right keyword yet, or the Arduino version of C++ doen't like the way I'm thinking. Or my thinking is just bent!

Can any experts out there point me in the right direction please?

Ta, Glyn

Normally I'd put the Fingers in a collection within Hand so I could refer to things like myHand.itsFinger(0).func();

Not in C++, you wouldn't.

myHand.itsFinger[0].func();

should work, though.

but the class object contains 4 very similar things

My hands have 5 fingers... ;)

the Arduino version of C++ doen't like the way I'm thinking.

It's not your way of thinking that is the problem. It's your way of translating that thinking into code that is the problem. So, (I'm sure everybody else knows whats coming next) post your code.

Well, as an anatomically correct programmer I thing of the thumb as not a finger...

Sillyness aside I may have got it right now. Putting together the example code showed me the error of my ways..

class Finger {
      public:
            int length(int length);
      private:
            int _length;
};

class Hand {
      public:
            Hand(int leftOrRight);
            int size(int size);
            Finger digits[4];
      private:
            int _size;
};


Hand::Hand(int leftOrRight) {
}

int Hand::size(int size) {
      _size=size;
}
int Finger::length(int length) {
      length=length;
}

Hand myHand(1);

void setup() {
      myHand.size(10);
      myHand.digits[1].length(0);

}

void loop() {
}

That appears to work.

Is that the way C++ is commonly used? I'm adding C++ to my repertoire with aid of these fun Arduinos.

Ta, Glyn

            int length(int length);

So, is length the name of a function or the name of a variable? You really want to re-think doing things like this.

What does size mean with respect to the hand?

      myHand.digits[1].length(0);

Amputated, eh? :smiley:

Aha, but now I have started I should enquire about another problem I had yesterday that I just faked my way around.

Suppose for a second that Hand has a function erm, skinTemperature() (getting hard to be believable here) now class Finger has a need to read the temperature of hand, I could pass Hand in in an init(Hand parent) sort of way.. Is that a good idea or is there better?

Thanks for your help, really appreciated.

Glyn

Hehehe, double use of length is normally avoided!

Nasty accidents happen..

BTW, I'm not really frankenstiniean. I'm coding up for the nRF24L01+ and the requirement is to handle the six pipes in the one chip.

Glyn

Aha, just spotted the modify button!

Currently, the Finger objects have no idea that they are collected in an array, or that the array is a member of an instance of another class. So, a finger knows nothing about the hand it is attached to.

You will need to tell each finger about the hand it belongs to, if there is any reason for the finger to know, either in an init() method as you suggest (though that method is typically, in the Arduino world, called begin()), or an argument to the appropriate finger method call.

float Finger::skinTemp(Hand &theHand)
{
   return theHand.getTemp();
}

And I call that from hand like:

myFinger[n].skinTemp(this);

'this' already being a pointer.

Yes, begin it should be - one should always adopt the proper house style.

I assume that with an array of class the passing of parameters to the constructor just aign't on?

Thanks for the power teaching!

Glyn

And I call that from hand like:

myFinger[n].skinTemp(this);

'this' already being a pointer.

The skinTemp function that I defined takes a reference, not a pointer, so, no this call is not correct.

You could change the definition of skinTemp() to take a pointer, and change the implementation to skinTemp() to use pointer notation.

float Finger::skinTemp(Hand *pHand)
{
   return pHand->getTemp();
}

OK, I think I get that (the syntax of pointers etc. is not yet second nature)

But when I try and bodge this into the example:

class Finger {
      public:
            void begin(Hand parent);
            int length(int length);
      private:
            int _length;
            Hand _parent;
};

class Hand {
      public:
            void begin();
            Hand(int leftOrRight);
            int size(int size);
            Finger digits[4];
      private:
            int _size;
};


Hand::Hand(int leftOrRight) {
}
void Hand::begin() {
      byte i;
      for (i=0; i < 4; i++) {
            digits[i].begin(this);
      }
}

int Hand::size(int size) {
      _size=size;
}
//--------------------------------

int Finger::length(int length) {
      length=length;
}
void Finger::begin(Hand &parent) {
      _parent = parent;
}

Hand myHand(1);

void setup() {
      myHand.size(10);
      myHand.digits[1].length(0);

}

void loop() {
}

I get a problem that Hand and Finger refernce each other, but I can only place one first in the compilation.

Also the syntax of Finger::begin is foxing me, both definition and calling.

Glyn

You don't want to pass an object of type hand to Finger::begin(). You want to pass either a reference (&) to an existing object or a pointer (*) to an existing object. In your case, you want to use a pointer.

You can use

class Hand;

before the Finger class, to tell that compiler that Hand IS a class, and that you'll tell it all about Hand in plenty of time.

OK, perhaps I’m getting there. With a few intermediate stages and some googling I get to:

class Hand;

class Finger {
      public:
            void begin(Hand *pParent);
            int length(int length);
            int tempf();
      private:
            int _length;
            Hand *_parent;
};

class Hand {
      public:
            void begin();
            Hand(int leftOrRight);
            int size(int size);
            int temph();
            Finger digits[4];
      private:
            int _size;
};


Hand::Hand(int leftOrRight) {
}
void Hand::begin() {
      byte i;
      for (i=0; i < 4; i++) {
            digits[i].begin(this);
      }
}

int Hand::size(int size) {
      _size=size;
}

int Hand::temph() {
      return (21);
}
//--------------------------------

int Finger::length(int length) {
      length=length;
}
void Finger::begin(Hand *pParent) {
      _parent = pParent;
}

int Finger::tempf() {
      int v = _parent->temph();
      return (v);
}

Hand myHand(1);

void setup() {
      myHand.size(10);
      myHand.digits[1].length(0);

}

void loop() {
}

Which compiles! Huzzah!

Now for some testing - and a little reading and rereading to try and bash this wierd (to me) syntax into my brain.

Many many thanks PaulS! Getting here would have taken a long time without you.

Glyn