Acessando Variáveis da Classe "Pai"

Olá a todos!
Primeiro gostaria de dizer que fiquei até surpreso por ter forum em português, então vou aproveitar! :smiley:

Tenho uma Classe Principal com uma Classe Secundária dentro dela.
O Objetivo dessa Classe Principal é controlar uma Lista.
O Objetivo da Secundária é ter acesso ao Item da Lista, e então controlar os Sub Itens (separados por ';').

Esta é apenas a estrutura que comecei a montar:

class MainClass{
  public:
    MainClass(){}
    int append(char* NewItem) {Serial.println("New Item append");}
    
    class SubClass{
      public:
        SubClass(int Index){_item = Index;}
        int append(char* NewItem) {strcat(Array[_item],NewItem);}
      private:
        int _item;
    };
  
    SubClass item(int Index) {}
  private:
     char* Array;
};

MainClass class1;

void setup(){
  Serial.begin(115200);
  class1.item(0).append("Item");
}

void loop(){}

Mas ao compilar recebo o erro:

Class.ino: In member function 'int MainClass::SubClass::append(char*)':
Class:16: error: invalid use of non-static data member 'MainClass::Array'
Class:9: error: from this location
invalid use of non-static data member 'MainClass::Array'

Como posso acessar as variáveis da Classe Principal através da secundária?
Agradeço a atenção!

Respondendo apenas para dizer que solucionei, especificamente passando uma referência da classe "pai" para a classe "filho".

Ainda bem que resolveu o problema. C++ não é propriamente o meu forte, por isso não sou o usuário melhor para responder a este tipo de questões. Apenas estou a escrever este comentário para o convidar a postar o resultado final do código, pois pode resolver o problema futuro de outro usuário.

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!

  • karma