C++ Methoden Durchlauf

Gast #2898702
Lesenswert?
• ▲
▼
Hallo zusammen, ich habe folgendes Problem:

ich habe 3 Klassen

class A
{
   ...
   public:
      meth1();
};

class B
{
   ...
   public:
      meth2();
};

class C
{
   ...
   public:
      meth3();
};

um Variable zu sein möchte ich die 3 Methoden je nach Konfiguration des 
Konstruktors in unterschiedlicher Reienfolge abarbeiten.

int main(void)
{
   ...
   for( u8TaskCount = 0u; u8TaskCount < u8MaxTasks; u8TaskCount++ )
   {
     // Je nach mitgabewert des Konstruktors
     meth1();
     meth3();
     meth2();

     // oder
     meth2();
     meth3();
   }
}

In C hätte ich das über eine Tabelle mit Funktionspointern gemacht aber 
in C++ habe ich noch keine Möglichkeit gefunden dieses Problem sauber zu 
lösen. Auf jeden Fall möchte ich keine Switch Case Abfrage verwenden.

Ich hoffe ihr könnt mir weiterhelfen.

Gruß Maraike
Gast #2898722
Lesenswert?
• ▲
▼
Über diesen Schritt bin ich schon längst hinaus. Also bitte keine 
Klugscheißer Kommentare mehr.

ACHTUNG - Der obige Code ist nur ein abstraktes Beispiel und kann 
natürlich nicht so compiliert werden - ACHTUNG
#2898725
Lesenswert?
• ▲
▼
Vermutlich soll die Hausaufgabenstellung folgendes Ergebnis bringen:

- Die drei Klassen erben von einer gemeinsamen Basis.
- Die Methode heißt immer gleich, und ist in der Basis als Virtuell 
markiert.
- Je nach Aufruf-Parameter wird eine Basisklassenpointer-Liste befüllt. 
(analog der Funktionspointer-Liste in C)
- Durchlaufen der Liste, Aufrufen der Methode auf jedem Element...
Gast #2898776
Lesenswert?
• ▲
▼
Hallo B*,

bitte gib kein Kommentar ab wenn du die Problematik noch nicht 
verstanden hast. Es ist keine Schande nachzufragen, vielleicht ist mein 
Beispiel nicht für jeden verständlich.

Wie im obigen Beispiel dargestellt existieren 3 Basisklassen mit ihren 
Methoden die vollkommen unterschiedlich heißen. Und ich möchte in einer 
Art Runtime diese Methoden ( die nichts mit einander gemein haben ) in 
unterschiedlicher Abfolge Abfragen.

Eine Klassenliste hilft mir da nicht weiter.

Hat vielleicht noch jemand eine Idee?
#2898782
Lesenswert?
• ▲
▼
Ich glaub der TO benötigt ein gutes C++ Tutorial

Ich fände folgenden Ansatz sehr viel besser:
1
class BaseTask
2
{
3
public:
4
  virtual void processingStep()=0;   
5
}
6

7
class Task1:public BaseTask
8
{
9
public:
10
  virtual void processingStep(){
11
    //tue was
12
  };   
13
}
14

15
class Task2:public BaseTask
16
{
17
public:
18
  virtual void processingStep(){
19
    //tue was anderes 
20
  };   
21
}
22

23
class Task3:public BaseTask
24
{
25
public:
26
  virtual void processingStep(){
27
    //tue was ganz anderes 
28
  };   
29
}
30

31
class BaseScheduler
32
{
33
public:
34
  virtual letATaskStep()=0;
35
  virtual addTask(BaseTask* i_task) = 0;
36
}
37

38
class RoundRobinScheduler : public BaseScheduler
39
{
40
public:
41
  RoundRobinScheduler()
42
   : m_curTask(0)
43
   , m_numTasks(0)
44
  {}
45
  static const int maxTasks = 10;
46

47
  virtual letATaskStep(){
48
    m_tasklist[m_curTask]->processingStep();
49
    ++m_curTask;
50
    if(m_curTask > m_numTasks)
51
      m_curTask = 0;
52
  }
53

54
  virtual addTask(BaseTask* i_task)
55
  {
56
    if(m_numTasks<maxTasks)
57
     m_tasklist[m_numTasks++] = i_task;
58
  }
59

60
private:
61
  int m_curTask;
62
  int m_numTasks;
63
  BaseTask* m_tasklist[maxTasks];
64
}
65

66
BaseScheduler* g_sched;
67

68
int main()
69
{
70
  RoundRobinScheduler rrsched;
71
  Task1 task1;
72
  Task2 task2;
73
  Task3 task3;
74
  g_sched = &rrsched;
75

76
  sched->addTask(&task1);
77
  sched->addTask(&task2);
78
  sched->addTask(&task3);
79

80
  for(;;)
81
  {
82
    sched->letATaskStep();
83
  }
84

85
}


PS: ich hab jetzt hier bewusst auf stl container verzichtet, um ohne 
dynamische Speicherverwaltung auszukommen.
Den Code könnte man somit auch auf einen kleinen µC einsetzen. Der 
Overhead durch die virtuellen Methoden wäre noch imho verschmerzbar.
#2898805
Lesenswert?
• ▲
▼
wenn die Klassen nix miteinander zu tun haben, außer eine identische 
Memberfunctions-Signatur, dann musst du dies nochmal verpacken.

du könntest zB, um bei meinem Beispiel zu bleiben eine template klasse 
schreiben, die von BaseTask ableitet und als konstruktorargument den 
Funktionspointer entgegennimmt.

Bin mir hier aber mit der Syntax nicht so richtig sicher
1
template <class T>
2
class GenericTask: public BaseTask
3
{
4
  typedef void (T* obj,  T::*MemberFunctionPointer) ();;
5
  GenericTask(  MemberFunctionPointer ptr )
6
   : m_ptr(ptr)
7
   , m_obj(obj)
8
  {}
9

10
  virtual void processingStep(){
11
    m_obj->(*m_ptr)();
12
  };   
13
  
14
private:
15
  T* m_obj;
16
  MemberFunctionPointer m_ptr;
17
};
18

19

20

21

22
...
23

24
int main()
25
{
26
  
27
  ...
28
  A a; // deine komische klasse
29
  GenericTask<A> gtA(&a, &(a->meth1) );
30
  B b; // deine komische klasse
31
  GenericTask<B> gtB(&b, &(b->meth2) );
32
  ...
33
  sched->addTask(&gtB);
34
}


edit:
Ergänzung im Code zur Benutzung.

Aber ich wette, dass der eigentliche Fehler in deinem Design der Klassen 
A, B, C liegt. Das ganze ist schon etwas krude

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