Forum: PC Hard- und Software C++ Pointer auf Klasseninterne Funktionen


von Markus F. (Firma: Turck Beierfeld GmbH) (markup)


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
};

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Auf welcher Instanz von "ParameterTest" soll denn "Checker" aufgerufen 
werden? Du musst eine Instanz angeben, wenn du einen 
Member-Funktions-Zeiger aufrufen willst.
Wenn der Aufruf ohne Instanz erfolgen soll, mach die Funktionen "static" 
und verwende normale Funktions-Zeiger statt Member-Funktions-Zeiger.

von Jemand (Gast)


Lesenswert?

Niklas G. schrieb:
> Du musst eine Instanz angeben, wenn du einen
> Member-Funktions-Zeiger aufrufen willst.

Syntaxbeispiel der Vollständigkeit halber:
1
ret = (this->*myParameterSet[i].Checker)(num1, num2);

von Markus F. (Firma: Turck Beierfeld GmbH) (markup)


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.

von Markus F. (Firma: Turck Beierfeld GmbH) (markup)


Lesenswert?

> Syntaxbeispiel der Vollständigkeit halber:
>
1
ret = (this->*myParameterSet[i].Checker)(num1, num2);


Super das läuft ohne Kompilierfehler durch. Dann geht es morgen ums 
testen.

Vielen Dank!

von Niklas G. (erlkoenig) Benutzerseite


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.

von Arc N. (arc)


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
};

von cppbert3 (Gast)


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

von Markus F. (Firma: Turck Beierfeld GmbH) (markup)


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.

von cppbert3 (Gast)


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

von Mark B. (markbrandis)


Lesenswert?

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? 🤔

von mh (Gast)


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.

von Yalu X. (yalu) (Moderator)


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;

von (Gast)


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.

von cppbert3 (Gast)


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

von mh (Gast)


Lesenswert?

cppbert3 schrieb:
> wenn die Menge des Code hier was "bringt" - warum dann nicht gleich die
> Zeile und Zeichen-Maximierung?

Wenn schon, dann mit
1
bool vergleich1 = false;
2
bool vergleich2 = false;
3
vergleich1 = num1 > num2;
4
vergleich2 = num1 <= num2;

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.