C++ Pointer auf Klasseninterne Funktionen

OP (Firma: Turck Beierfeld GmbH) #6545793
Lesenswert?

Schönen guten Abend,

in versuche recht neu in c++ einzusteigen und stehe derzeit vor einem 
Problem. Allgemein versuche ich die wieder Verwendbarkeit des Codes im 
Auge zu behalten.

Ziel: Es soll ein Modul geschrieben werden, welches nur an einer Stelle 
angepasst werden muss und dann dementsprechend für andere Projekte 
verwendet werden kann. Diese Prüfungen sind nicht statisch und können 
sich selbst bei einer Variante, je nach der Konfiguration unterscheiden. 
Bei mir geht es um eine typische Busverbindung mit Index basierenden 
Zugriff.

Ich habe dazu einmal eine stark vereinfachte Klasse geschrieben. Diese 
hat derzeit 2 Check Funktionen (biggerCheck und smallerCheck). Es soll 
jetzt in der Hauptfunktion eine Idee und 2 Zahlen übergeben werden und 
die Funktion schaut nach ob der Eintrag in der Parameter Liste vorhanden 
ist und führt die hinterlegte Check Funktion aus.

Wenn ich dies versuche zu Kompilieren erhalte ich die Meldung:
1
error C2064: Ausdruck ergibt keine Funktion, die 2 Argumente übernimmt
Diese Meldung kommt von der Zeile
1
ret = ((myParameterSet[i].Checker)(num1, num2));

Also werde ich etwas bei der Definition oder beim Aufrufen verkehrt 
gemacht werden, ich komme derzeit jedoch nicht weiter. Ich hatte ebenso 
die Meldung bei der Schreibweise:
1
ret = myParameterSet[i].Checker(num1, num2);

Kann mir dort vielleicht einer kurz auf die Sprünge helfen?
1
class ParameterTest
2
{
3
  #define PARAM_LIST_SIZE 4
4

5
  typedef  bool(ParameterTest::*functor_testFnc) (uint8_t, uint8_t);
6
  typedef struct
7
  {
8
    uint8_t      refIndex;
9
    functor_testFnc  Checker;    /* check if the written value in range */
10
  }ParameterSet_Type;
11

12
  bool biggerCheck(uint8_t num1, uint8_t num2)
13
  {
14
    bool ret;
15
    if (num1 > num2)
16
    {
17
      ret = true;
18
    }
19
    else
20
    {
21
      ret = false;
22
    }
23
    return(ret);
24
  }
25

26
  bool smallerCheck(uint8_t num1, uint8_t num2)
27
  {
28
    bool ret;
29
    if (num1 < num2)
30
    {
31
      ret = true;
32
    }
33
    else
34
    {
35
      ret = false;
36
    }
37
    return(ret);
38
  }
39

40

41
  const ParameterSet_Type myParameterSet[PARAM_LIST_SIZE] =
42
  {
43
    {  0, &ParameterTest::biggerCheck },
44
    {  1, &ParameterTest::smallerCheck },
45
    {  21, &ParameterTest::biggerCheck },
46
    {  42, &ParameterTest::smallerCheck }
47
  };
48

49
public:
50
  bool doCheck(uint8_t id, uint8_t num1, uint8_t num2)
51
  {
52
    bool ret = false;
53
    for (uint8_t i = 0; i < PARAM_LIST_SIZE; i++)
54
    {
55
      if (myParameterSet[i].refIndex == id)
56
      {
57
        ret = ((myParameterSet[i].Checker)(num1, num2));
58
      }
59
    }
60
    return(ret);
61
  }
62
};
OP (Firma: Turck Beierfeld GmbH) #6545817
Lesenswert?

Der Checker soll voraussichtlich in einer Klasse aufgerufen werden, 
welche alle Information von ParameterTest erbt.

Mit statischen Funktionen funktioniert das Konstrukt in c recht einfach. 
Jetzt muss ich jedoch auf gewisse Daten in andere Klassen bei mir in den 
Checks zugreifen und das hätte ich versucht über friends zu lösen.

Stehe anderen Lösungen aber auch offen gegenüber.
Persönliche Seite #6545821
Lesenswert?

Markus F. schrieb:
> Jetzt muss ich jedoch auf gewisse Daten in andere Klassen bei mir in den
> Checks zugreifen und das hätte ich versucht über friends zu lösen.

Das, und public/private, hat überhaupt nichts mit dem Problem zu tun. Es 
geht nur darum, auf welcher Instanz die Funktion aufgerufen werden soll. 
Wahrscheinlich ist Jemand's Lösung das was du suchst.
#6545844
Lesenswert?

Etwas moderner darf die Lösung schon sein oder darf/kann nur C++ vor 
C++11 verwendet werden?
1
using CheckFun = std::function<bool(uint8_t, uint8_t)>;
2

3
struct ParameterSet {
4
    uint8_t RefIndex;
5
    CheckFun Function;
6
};
7

8
class ParameterTest {
9
    CheckFun larger = [](uint8_t n1, uint8_t n2) { return n1 > n2; };
10
    CheckFun smaller = [](uint8_t n1, uint8_t n2) { return n1 < n2; };
11
    std::vector<ParameterSet> parameters = { 
12
        { 0, larger }, 
13
        { 1, smaller }, 
14
        { 21, larger }, 
15
        { 42, smaller } 
16
    };
17
public:
18
    bool DoCheck(uint8_t id, uint8_t n1, uint8_t n2) {
19
        for (auto p : parameters) {
20
            if (p.RefIndex == id) return p.Function(n1, n2);
21
        }
22
        return false;
23
    }
24
};
Gast #6545922
Lesenswert?

Markus F. schrieb:
> bool biggerCheck(uint8_t num1, uint8_t num2)
>   {
>     bool ret;
>     if (num1 > num2)
>     {
>       ret = true;
>     }
>     else
>     {
>       ret = false;
>     }
>     return(ret);
>   }

Auch wenn das vielleicht nur ein Beispiel ist, aber

return num1 > num2;

ist mehr als ausreichend und verständlich
OP (Firma: Turck Beierfeld GmbH) #6546285
Lesenswert?

Arc N. schrieb:
> Etwas moderner darf die Lösung schon sein oder darf/kann nur C++ vor
> C++11 verwendet werden?

Vielen Dank, die Lösung gefällt mir auf anhieb besser. Ich hatte mich 
derzeit noch daran gescheut Funktionen aus der STL zu nehmen, da ich 
gerade erst angefangen habe, mich in dieser einzuarbeiten.

Ich bin derzeit am schauen, scheinbar unterstützt der GCC (V 6.3.1) aus 
dem Atmel Studio C++11, also werde ich das gleich umbauen.
Gast #6546316
Lesenswert?

cppbert3 schrieb:
>> bool biggerCheck(uint8_t num1, uint8_t num2)
>>   {
>>     bool ret;
>>     if (num1 > num2)
>>     {
>>       ret = true;
>>     }
>>     else
>>     {
>>       ret = false;
>>     }
>>     return(ret);
>>   }

als Reminder: das würde dir bei einem Review von jedem guten Entwickler 
angekreidet werden

kannst auch
1
bool ret = num1 > num2;
2
return ret;

schreiben aber alles andere ist wirklich totaler murks - zeigt das dir 
vielleicht nicht klar ist das num1 > num2 direkt auf bool evaluiert d.h. 
dein Code sachen macht die der Kompiler genau so auch macht
Gast #6546360
Lesenswert?

Mark B. schrieb:
> cppbert3 schrieb:
>> Auch wenn das vielleicht nur ein Beispiel ist, aber
>>
>> return num1 > num2;
>>
>> ist mehr als ausreichend und verständlich
>
> Woher kommt dieser Aberglaube, dass Code automatisch besser wird wenn
> man ihn in weniger Zeilen quetscht? 🤔

Man könnte genauso gut fragen:
Woher kommt dieser Aberglaube, dass Code automatisch besser wird wenn
man ihn in über mehr Zeilen verteilt? 🤔

Für mich ist
1
bool biggerCheck(uint8_t num1, uint8_t num2)
2
{
3
    return num1 > num2;
4
}
deutlich besser lesbar als
1
bool biggerCheck(uint8_t num1, uint8_t num2)
2
{
3
    bool ret;
4
    if (num1 > num2)
5
    {
6
        ret = true;
7
    }
8
    else
9
    {
10
        ret = false;
11
    }
12
    return(ret);
13
}

Vor allem wenn man bedenkt, dass sich biggerCheck und smallerCheck in 
nur einem Zeichen unterscheiden.
Moderator #6546438
Lesenswert?

Mark B. schrieb:
> cppbert3 schrieb:
>> Auch wenn das vielleicht nur ein Beispiel ist, aber
>>
>> return num1 > num2;
>>
>> ist mehr als ausreichend und verständlich
>
> Woher kommt dieser Aberglaube, dass Code automatisch besser wird wenn
> man ihn in weniger Zeilen quetscht? 🤔

Nicht automatisch, aber in diesem Fall schon. Da wird auch nichts
gequetscht, sondern nur sinnloses Zeug weggelassen.

Die meisten Leute schreiben ja auch nicht

1
  if (x + y == 0)
2
    sum = 0;
3
  else if (x + y == 1)
4
    sum = 1;
5
  else if (x + y == 2)
6
    sum = 2;
7
  else if (x + y == 3)
8
    sum = 3;
9
  ...

sondern "quetschen" das zu einer Zeile zusammen:

1
  sum = x + y;
Gast #6546452
Lesenswert?

Markus F. schrieb:
> Arc N. schrieb:
>> Etwas moderner darf die Lösung schon sein oder darf/kann nur C++ vor
>> C++11 verwendet werden?
>
> Vielen Dank, die Lösung gefällt mir auf anhieb besser. Ich hatte mich
> derzeit noch daran gescheut Funktionen aus der STL zu nehmen, da ich
> gerade erst angefangen habe, mich in dieser einzuarbeiten.
>
> Ich bin derzeit am schauen, scheinbar unterstützt der GCC (V 6.3.1) aus
> dem Atmel Studio C++11, also werde ich das gleich umbauen.

Auf dem kleinen µC ist Vorsicht geboten bei der Verwendung von 
std::function, das benötigt unter Umständen dynamisch allozierten 
Speicher.

So wie es aussieht greifen smallerCheck und biggerCheck auf keine 
Instanzvariablen oder -methoden zu, dann könnte man die beiden Methoden 
also schon "static" machen, man benötigt dann auch keinen Zeiger auf die 
Instanz mehr.
Gast #6546535
Lesenswert?

Mark B. schrieb:
> cppbert3 schrieb:
>> Auch wenn das vielleicht nur ein Beispiel ist, aber
>>
>> return num1 > num2;
>>
>> ist mehr als ausreichend und verständlich
>
> Woher kommt dieser Aberglaube, dass Code automatisch besser wird wenn
> man ihn in weniger Zeilen quetscht? 🤔

Vielleicht weil diese 10 Zeilen exakt 0 Mehrwert bringen?

wenn die Menge des Code hier was "bringt" - warum dann nicht gleich die 
Zeile und Zeichen-Maximierung?
1
bool biggerCheck(uint8_t num1, uint8_t num2)
2
{
3
    bool ret;
4
    bool vergleich;
5
    vergleich = num1 > num2;
6
    if (vergleich == true)
7
    {
8
        ret = true;
9
    }
10
    else if(vergleich == false)
11
    {
12
        ret = false;
13
    }
14
    return(ret);
15
}

weils noch sinnfreier ist

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren