Então aqui está o exemplo:
.h
# ifndef stringList_h
# define stringList_h
#include <Arduino.h>
#include <string.h>
//------------------------------------------------------------------------
#define DELIMITER_CHAR ';'
#define makeList(x) ((char*)x)
class stringList
{
public:
stringList() {}
void setup(char* Items, int MaxItems, int ItemsMaxLength);
void assign(char* Items);
void assign(char* Items, int MaxItems, int ItemsMaxLength);
int size();
void clear();
void sort();
void sortReverse();
void reverse();
void shuffle();
void lower();
void upper();
int append(char* NewItem);
bool modify(int Index, char* NewItem);
inline bool modify(char* Item, char* NewItem, int From=0);
bool remove(int Index);
inline bool remove(char* Item, int From=0);
bool getItem(int Index, char* Buffer, int Length);
int getIndex(char* Item, int From=0);
private:
class SubItem
{
public:
SubItem(int Index, stringList* List) {_index = Index; _list = List;}
int append(char* NewItem);
bool modify(int Index, char* NewItem);
inline bool modify(char* Item, char* NewItem, int From=0);
bool remove(int Index);
inline bool remove(char* Item, int From=0);
bool getItem(int Index, char* Buffer, int Length);
int getIndex(char* Item, int From=0);
private:
inline char* element() { return &_list->array[(_index)*_list->itemsMaxLength]; }
int _index;
stringList* _list;
};
public:
SubItem item(int Index){ return SubItem(Index, this); }
private:
inline char* element(int Index) { return &array[(Index)*itemsMaxLength]; }
char* array;
int nItems, itemsMaxLength, maxItems;
int activeIndex;
int activeSubIndex;
};
#endif
.cpp
#include "stringList.h"
//--------------------------------------------------------------------------------
// Abaixo são as funções da classe "pai" stringList
//--------------------------------------------------------------------------------
void stringList::setup(char* Items, int MaxItems, int ItemsMaxLength){
maxItems = MaxItems;
itemsMaxLength = ItemsMaxLength;
if(Items!=NULL){
array = Items;
nItems = 0;
for(int n=maxItems-1; n>=0; n--){
if(strlen(element(n))>0){
if(n+1>nItems)
nItems = n+1;
break;
}
}
}
}
void stringList::append(char* NewItem){
if(nItems >= maxItems || strlen(NewItem)<=0)
return -1;
char buffer[strlen(NewItem)+1];
memset(buffer,0,sizeof(buffer));
strcpy(buffer,NewItem);
if(strlen(buffer)<=0 || strlen(buffer)>=itemsMaxLength)
return -1;
else if(strlen(element(0))>0)
nItems++;
strcpy(element(nItems-1),buffer);
if(nItems==1)
activeIndex = 0;
return nItems-1;
}
/* OUTRAS FUNÇÕES */
/* ... */
//--------------------------------------------------------------------------------
// Abaixo são as funções da classe "filha" SubItem
//--------------------------------------------------------------------------------
int stringList::SubItem::append(char* NewItem){
if( _list->itemsMaxLength - 2 - strlen(element()) < strlen(NewItem) )
return -1;
element()[strlen(element())] = DELIMITER_CHAR;
strcat(element(),NewItem);
int count = 0;
int len = strlen(element());
for(int n = 0; n<len; n++){
if(element()[n]==DELIMITER_CHAR)
count++;
}
return count + 1;
}
/* OUTRAS FUNÇÕES */
/* ... */
Eu não puis todas as funções no .cpp (para ficar mais objetivo), mas se for preciso, eu posso colocar.
Eu fiz essa estrutura para substituir uma função como essa:
stringList myList;
myList.appendSubItem(int Item, char* NewItem);
por uma assim:
stringList myList;
myList.item(int Item).append(char* NewItem);
Acho que fica mais limpo e legível, mas realmente era só para não usar nomes cumpridos.
Explicação:
A função item() da classe stringList retorna uma instancia da classe SubItem, daí que eu posso colocar uma função em "cadeia" utilizando o ponto, como se usa para um membro de classe.
Nesta função item(), ele também inicializa a classe SubItem, passando o índice do item que quer manipular, junto a uma referência a instância da classe stringList, ao qual estou chamando a função item().
Essa instância é chama como this no contexto da classe "pai"
Sem passar essa referência, não é possível acessar as varíaveis da classe "pai" (poderia passá-las pelo construtor também, porem a sintaxe ficaria longa).
Para acessar as variáveis ou funções da classe "pai", na classe "filha" tem uma referência do "pai", então tem que usar o operador de apontador de classe (acho que é esse o nome em português), que é o ->
Então seria assim:
refDoPai->varDoPai
refDoPai->funcDoPai
Olhando os exemplos, acho que dá para entender.
Espero ter conseguido explicar direito!