PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : "alias" einer Klassen-Instanz als Verweis auf "echte" Instanz



HaWe
07.12.2018, 15:01
hallo
ein neues Klassen-Problem:

ich habe eine

class tMenu {
protected:
public:
tMenu(int a, int b) { }
int test;
void init() {}
};

// und 3 (oder auch deutlich mehr) Instanzen
tmenu menu0, menu02, menu23;

Ich möchte die aktuell behandelte Instanz jetzt immer als alias
actMenu
ansprechen, in der Art

actMenu = menu0;
actMenu.init(); // initialisiert menu0
actMenu.test=123; // setzt jetzt menu0.test=123
(Also selbe Syntax als wäre das alias eine reale Instanz)


und später auch ein weiteres alias für den Vorgänger:
preMenu = menu0;
actMenu = menu02;
wobei dann wieder Zugriffe erfolgen sollen z.B. als
actMenu.test=999; // setzt jetzt menu02.test=999
für die "neue aktuelle" Instanz

Später dann je nach Programmfluss wieder neue willkürliche actMenu und preMenu Verweise, entweder dann eben menu23 oder auch wieder menu0.

Wie kann man diesen alias-Verweis-Mechanismus richtig programmieren?
Über Pointer * oder Pointeradressen & oder beides ?

shedepe
07.12.2018, 15:15
tMenu menu0(10,20);
tMenu* name = &menu0;

name->init();

alternativ:

tMenu menu0(10,20);
tMenu & name = menu0;
name.init();

HaWe
07.12.2018, 15:36
dankeschön für die schnelle Antwort!
Beide super, das zweite sogar noch einen Tick besser, da nur ein . und kein -> nötig!
Vielen Dank nochmals!

- - - Aktualisiert - - -

hm - klappt noch nicht ganz:

ich habe initialisiert:

// global:

tMenu menu0(10,20);
tMenu menu02(10,20);

tMenu & actMenu = menu0;
tMenu & preMenu = menu0;

aber bei den aktuellen Zuweisungen klappt es noch nicht:


&actMenu = menu02; // error: exit status 1 lvalue required as left operand of assignment

shedepe
07.12.2018, 16:00
Zeig mal deinen genauen Code. Ich glaube du hast wieder ein Copy Pastefehler

tMenu & actMenu = menu0; <-- Da ist gar kein menu02.

Edit:
Als Beispiel:



// Example program
#include <iostream>
#include <string>
class test
{
public:
int a;
};
int main()
{
test instance;
test & aliasTest = instance;
}

Getestet mit: http://cpp.sh/


Geht auch global:
// Example program
#include <iostream>
#include <string>
class test
{
public:
int a;
};
test instance;
test & aliasTest = instance;
int main()
{
std::cout << instance.a << std::endl;
aliasTest.a = 10;
std::cout << aliasTest.a << std::endl;
}

HaWe
07.12.2018, 16:05
ich hatte es nur nachträglich geändert, zur Verdeutlichung, aber das menu02 ist auch da.

Der vollständige Code ist ein wenig erweitert gegenüber dem gekürzten Beispiel - hoffe, es ist nicht zuviel ;)





// i2c
#include <Wire.h> // Incl I2C comm, but needed for not getting compile error
#define ESPSDA D2 // defaults
#define ESPSCL D1 //

// TFT
//#include <Adafruit_SSD1306.h>
#include <ESP_SSD1306.h> // Modification of Adafruit_SSD1306 for ESP8266 compatibility
#include <Adafruit_GFX.h> // Needs a little change in original Adafruit library (See README.txt file)
#include <Fonts/FreeSans12pt7b.h> //
#include <Fonts/FreeSansBold12pt7b.h> //
#include <Fonts/FreeSans9pt7b.h> //
#include <Fonts/FreeMono12pt7b.h> //
#include <Fonts/FreeMono9pt7b.h>
// Pin definitions

//----------------------------------------------------------------------------
// display driver
//----------------------------------------------------------------------------
#define OLED_RESET 10 // GPIO10=D12 Pin RESET signal (virtual)

//Adafruit_SSD1306 display(OLED_RESET);
//Adafruit_SSD1306 display(128, 64, &Wire, OLED_RESET);
ESP_SSD1306 display(OLED_RESET);


//----------------------------------------------------------------------------
// ButtonClass buttons
//----------------------------------------------------------------------------

#include <ButtonClass.h>
// 3 buttons for menu control
tButton btn0;
tButton btn1;
tButton btnfx;



//----------------------------------------------------------------------------
// OLED menu
//----------------------------------------------------------------------------

class tMenu {
protected:
int16_t MENULEN, LINELEN, VISLNUM, FONTHI;
char buf[20];
int8_t firstvln, lastvln, displn;

public:
int16_t ID, pre_ID;
int8_t act, pre_act;
char **list;
int test;

tMenu (int16_t menulen, int16_t linelen, int16_t id) // constructor
{
firstvln=0; lastvln=0; displn=0;
pre_ID=0;
act=0;
pre_act=0;
MENULEN = menulen; // number of available menu options
LINELEN = linelen; // line length of menu options
ID = id;

list = new char*[MENULEN];
for(int i = 0; i < MENULEN; i++)
{
list[i] = new char[LINELEN+1];
}
}

void init(int16_t vislnum=5, byte fonthi=13 ) { // ()=defaults=(5,13)
for(int i=0; i<MENULEN; i++) {
sprintf(buf,"%d .......|", i);
strncpy(list[i], buf, LINELEN);
VISLNUM = vislnum; // number of visible menu options
FONTHI = fonthi;
}
}

void mdisplay() {
if(act>VISLNUM-1) firstvln=_min(act-1, MENULEN-VISLNUM);
else firstvln=0;
lastvln=firstvln+VISLNUM-1;
display.clearDisplay();
for(byte i=firstvln; i<=lastvln; i++) {
displn=(FONTHI-3) + (i-firstvln)*FONTHI;
if(i==act) {
display.setCursor(0, displn); display.print('>');
Serial.print('>');
}
else Serial.print(' ');
Serial.println(list[i]);
display.setCursor(11, displn); display.print(list[i]);
}
display.display();
Serial.println();
}

int32_t checkbtn(int8_t btop, int8_t bbtm, int8_t bfunc) {
if(btop==1){ // dec
if(act>0) act--;
//Serial.print ("^"); Serial.println(act);
mdisplay();
return 11 ;
}
if(btop==3){ // min
act=0;
//Serial.print ("^"); Serial.println(act);
mdisplay();
return 13 ;
}
if(bbtm==1){ // inc
if(act<MENULEN-1) act++;
//Serial.print ("v"); Serial.println(act);
mdisplay();
return 21;
}
if(bbtm==3){ // max
act=MENULEN-1;
//Serial.print ("v"); Serial.println(act);
mdisplay();
return 23;
}
if(bfunc==1){
sprintf(buf,"Menu %d-%d ToDo=%d", ID,act,bfunc);
Serial.println(buf);
return 1;
}
if(bfunc==2){
sprintf(buf,"Menu %d-%d ToDo=%d", ID,act,bfunc);
Serial.println(buf);
}
if(bfunc==3){
sprintf(buf,"Menu %d-%d ToDo=%d", ID,act,bfunc);
Serial.println(buf);
return 3;
}
return 0;
}

~tMenu() { // destructor
// Dynamically delete the array
delete[] list ;
}
};


tMenu menu0(10,20, 0); // numEntries, lineLength, menuID;
tMenu menu02(10,20, 2);


tMenu & actMenu = menu0;
tMenu & preMenu = menu0;





//----------------------------------------------------------------------------
// OLED dashboard
//----------------------------------------------------------------------------

void dashboard(byte mode) {

display.clearDisplay();
display.setFont();

if (mode == 0) {
display.setFont(); // h=8.0 pt
display.setCursor( 0, 0); display.print(" 0 Hello World 1");
}
display.display();
display.setFont();
}



void setup(void)
{
// Start Serial
//pinMode(D3, OUTPUT); // + LED_BUILTIN


btn0.init(D6, INPUT_PULLUP, 50);
btn1.init(D3, INPUT_PULLUP, 50);
btnfx.init(D4, INPUT_PULLUP, 50);


//pinMode(D7, OUTPUT);
//pinMode(D8, OUTPUT);

Serial.begin(115200);
delay(2000); // wait for Serial()
Serial.println("Serial started");


// Start Wire (SDA, SCL)
//Wire.begin(ESPSDA,ESPSCL); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Wire.begin();

// SSD1306 Init
display.begin(SSD1306_SWITCHCAPVCC); // Switch OLED
//display.begin(SSD1306_SWITCHCAPVCC, 0x3D, true, false);
display.setRotation(2);
display.clearDisplay(); // Clear the buffer.

// text display tests
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println("Hello, world!");
display.display();

//--------------------------------------
// test + debug

Serial.println();
for(byte i=0; i<10; i++) {
Serial.print("-");
Serial.println(menu0.list[i]);
}
menu0.init(); // optional numVisibleLines, fontHeight; defaults = (5,13)
display.clearDisplay();
display.display();

display.setFont(&FreeMono9pt7b); // h=13.10pt
menu0.mdisplay();
}


void loop() {
int32_t result;

result = menu0.checkbtn(btn0.click(), btn1.click(), btnfx.click() );

&actMenu = menu02; // test


}

shedepe
07.12.2018, 16:09
tMenu menu0(10,20, 0); // numEntries, lineLength, menuID;
tMenu menu02(10,20, 0);


tMenu & actMenu = menu0;
tMenu & preMenu = menu0;


Du machst dort defintiv keine Zuweisung auf menu02.

Und da solltest du dir noch mal C++ Grundlagen durchlesen ;) https://www.tutorialspoint.com/cplusplus/cpp_references.htm
&actMenu = menu02;

Wenn dann:
actMenu = menu02;

HaWe
07.12.2018, 17:49
nein, oben nicht, aber in loop
Beim Initialisieren nur auf menu0 initialisiert,
erst in loop wird testweise actmenu auf menu2 initialisiert.

- - - Aktualisiert - - -

moment....

- - - Aktualisiert - - -




tMenu menu0(10,20, 0); // numEntries, lineLength, menuID;
tMenu menu02(10,20, 2);

tMenu & actMenu = menu0;
tMenu & preMenu = menu0;


void setup() {
menu0.init(); // optional numVisibleLines, fontHeight; defaults = (5,13)
Serial.println(menu0.ID);
Serial.println(actMenu.ID);
actMenu.mdisplay();

actMenu = menu02; // test
actMenu.init();
Serial.println(menu02.ID);
Serial.println(actMenu.ID);
actMenu.mdisplay();



ergibt jetzt völlig korrekt




0
0
>0 .......|
1 .......|
2 .......|
3 .......|
4 .......|

2
2
>0 .......|
1 .......|
2 .......|
3 .......|
4 .......|




super, habs kapiert, dankeschön! :D


- - - Aktualisiert - - -

noch ein unerwarteter bug im Programm:



tMenu menu0(10,20, 0); // numEntries, lineLength, menuID=0;
tMenu menu02(10,20, 2); // numEntries, lineLength, menuID=2;

tMenu & actMenu = menu0;
tMenu & preMenu = menu0;

void init() {
//
display.setFont(&FreeMono9pt7b); // h=13.10pt
display.clearDisplay();
display.display();

Serial.println("Menu 0+02 init:");
menu0.init();
strcpy(menu0.list[0], " menu0");
Serial.print("menu0.ID="); Serial.println(menu0.ID); //<<<<<<<<<< stimmt noch !!

menu02.init();
strcpy(menu02.list[0], " menu02");
Serial.print("menu02.ID="); Serial.println(menu02.ID); //<<<<<<<<<< stimmt noch !!
Serial.println();
Serial.println("actMenu-Zuweisungen:");
Serial.println();

actMenu=menu0;
Serial.println("actMenu=0");
Serial.print("menu0.ID="); Serial.println(menu0.ID); // noch ok
Serial.print("menu02.ID="); Serial.println(menu02.ID);
Serial.print("actMenu.ID="); Serial.println(actMenu.ID);
actMenu.mdisplay(); // noch ok


Serial.println("actMenu=02");
actMenu = menu02; // test
Serial.print("menu0.ID="); Serial.println(menu0.ID); // Fehler
Serial.print("menu02.ID="); Serial.println(menu02.ID);
Serial.print("actMenu.ID="); Serial.println(actMenu.ID);
actMenu.mdisplay();

Serial.println("actMenu=0");
actMenu = menu0; // und wieder zurück
Serial.print("menu0.ID="); Serial.println(menu0.ID); // Fehler
Serial.print("menu02.ID="); Serial.println(menu02.ID);
Serial.print("actMenu.ID="); Serial.println(actMenu.ID); // Fehler
actMenu.mdisplay(); // Fehler
delay(1);




bis nach der 1. Zuweisung actMenu=menu0 ist noch alles ok,
nach der Neuzuweisung actMenu=menu02 ist der Inhalt von Original-menu0 überschrieben:


Menu 0+02 init:
menu0.ID=0 // ok!
menu02.ID=2 // ok!

actMenu-Zuweisungen:

actMenu=0
menu0.ID=0 // ok!
menu02.ID=2
actMenu.ID=0
> menu0 // ok
1 .......|
2 .......|
3 .......|
4 .......|

actMenu=02
menu0.ID=2 // Fehler!
menu02.ID=2
actMenu.ID=2
> menu02 // ok
1 .......|
2 .......|
3 .......|
4 .......|

actMenu=0
menu0.ID=2 // Fehler!
menu02.ID=2
actMenu.ID=2 // Fehler!
> menu02 // Fehler!
1 .......|
2 .......|
3 .......|
4 .......|

HaWe
08.12.2018, 09:27
ob ich schon wieder betriebsblind gegen eigene dumme Fehler bin...?

shedepe
08.12.2018, 09:36
https://www.tutorialspoint.com/cplusplus/cpp_references.htm
Punkt 2

HaWe
08.12.2018, 09:49
oh -

Once a reference is initialized to an object, it cannot be changed to refer to another object. Pointers can be pointed to another object at any time.
das ist ja Mist... :-/
Dann probiere ich es vlt doch mal so

tMenu menu0(10,20);
tMenu* name = &menu0;
name->init();

oder vlt fällt mir auch noch was ganz anderes ein, mit Steuerung direkt aus dem Objekt heraus
- ich brauche ja eh eine längere verkettete Liste von Vorgängern und Nachfolgern

HaWe
08.12.2018, 17:21
jo, Verkettung klappt intern mit

class tMenu {

public:
tMenu* preMenu;

}
:!:
besten Dank nochmals! 8)