Forum: PC-Programmierung Visitor Pattern C++ => Invalid Use of incomplete type


von Milhouse (Gast)


Lesenswert?

Hallo zusammen,

ich versuche das Visitor Pattern nach der Wiki-Vorlage zu verwenden:
https://en.wikipedia.org/wiki/Visitor_pattern#C.2B.2B_example
Doch bekomme ich im Client bei dem Aufruf der Dispatch Methode die 
Meldung der Typ sei incomplete. Was ich nicht verstehe, da mir die 
Methode "DispShowCall()"sogar vorgeschlagen wurde.

Hat jemand einen Vorschlag?
1
>>Der Client "Node_Junction"
2
>#include "..\UIs\ui_visitor_i.h"
3
>class Node_Junction : public Node_I
4
>{
5
>public:
6
>    Node_Junction(int arg = 0);
7
>  virtual void Show(UI_Visitor_I *uiVisitor) override
8
>    {
9
>        (*uiVisitor).DispShowCall(this);
10
>    }
11
12
>>Das Interface des Visitors
13
>#include "..\std\Node_Junction.h"
14
>class Node_Junction;
15
>class UI_Visitor_I
16
>{
17
>public:
18
>    virtual void DispShowCall(Node_Junction* caller)=0;
19
>};
20
21
>>Implementierung des Visitor Interfaces
22
>#include "..\..\share\UIs\ui_visitor_i.h"
23
>
24
>namespace Ui {
25
>class Ui_Visitor;
26
>}
27
>
28
>class Ui_Visitor : public QWidget,  public UI_Visitor_I
29
>{
30
>    Q_OBJECT
31
>public:
32
>    explicit Ui_Visitor(QWidget *parent = 0);
33
>    ~Ui_Visitor();
34
>    virtual void DispShowCall(Node_Junction* caller)override;

--

Mit den Tags für Formatierung wird es etwas besser ... aber ich entferne 
nicht die beknackten Spitzklammern.

-rufus

: Bearbeitet durch User
von g457 (Gast)


Lesenswert?

> Doch bekomme ich im Client bei dem Aufruf der Dispatch Methode die
> Meldung der Typ sei incomplete.

Ich sehe weder eine Methode 'Dispatch()', noch einen Aufruf selbiger, 
und schon garkeine Compilermeldung.

> Hat jemand einen Vorschlag?

Originalcode und -fehlermeldung zeigen, nicht irgendetwas das zufällig 
in der Zwischenablage war.

von Milhouse (Gast)


Lesenswert?

>Ich sehe weder eine Methode 'Dispatch()', noch einen Aufruf selbiger,
>und schon garkeine Compilermeldung.

Was meinst du wohl, soll
>DispShowCall();
heißen.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Hallo Fremder,

Nur mal so als Tipp: das ist hier keine kostenpflichtige 
Beratungsstelle, für die Dein Arbeitgeber bezahlt hat.

Was kann den so schwerr daran sein, den gezeigten Code so zu 
formatieren/annotieren, dass man ihn lesen kann? (direkt über dem Feld, 
in den Du den code gerotzt hast, gibt es Informationen zu Formatierung).

Warum zeigst Du uns nicht die Fehlermeldung des compilers? Du fragst 
uns, was der Compiler damit meint, gibst uns aber nur eine von Dir 
interpretierte Version.

Wenn Dich jemand nach mehr Details fragt: warum gibst Du ihm dann nicht 
die Information? (und entschuldigst ggf. sogar dafür, dass Du das im 
ursprünglichen Post vergessen hattest). Du guckst da schon seit Stunden 
auf Dein Problem und übersiehst dabei vielleicht, dass Du beim 
Formulieren Deiner Frage wichtige Details vergessen hast.

So, jetzt zu eigentlichen Frage:

Wenn der Compiler sich über einen "incomplete type" beschwerrt, dann hat 
er halt an dieser Stelle bis dato nur einen "incomplete type" (aka 
forward declaration) gesehen. Wenn das tatsächlich beim Versuch, über 
einen Pointer oder eine Referenz auf ein Objekt eine member function 
aufzurufen, dann fehlt halt die Definition der Klasse.

Wahrscheinlich Node_I. Da können wir aber auch nur raten, da der von Dir 
gepostete Code keinen einzigen Funktionsaufruf enthält.

mfg Torsten

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Milhouse schrieb:
> ich versuche das Visitor Pattern nach der Wiki-Vorlage zu verwenden:
> https://en.wikipedia.org/wiki/Visitor_pattern#C.2B.2B_example
> Doch bekomme ich im Client bei dem Aufruf der Dispatch Methode die
> Meldung der Typ sei incomplete.

Dann ist das wohl so.

> Was ich nicht verstehe, da mir die
> Methode "DispShowCall()"sogar vorgeschlagen wurde.

Vom Compiler?

> Hat jemand einen Vorschlag?

Von Incomplete Types kannst du i.W. Adressen herumschubsen, mehr nicht.

>>>Der Client "Node_Junction"
>>#include "..\UIs\ui_visitor_i.h"

Tippfhler.  "/" anstatt "\" — und ja, auch under Windos und auch wenn's 
in Wikipedia mit "\" stehen sollte.

>>class Node_Junction : public Node_I
>>{
>>public:
>>    Node_Junction(int arg = 0);
>>  virtual void Show(UI_Visitor_I *uiVisitor) override
>>    {
>>        (*uiVisitor).DispShowCall(this);
>>    }

UI_Visitor_I ist offenbar incomplete; insbesondere kannst du keinen 
Zeiger darauf dereferenzieren, was du mit uiVisitor->DispShowCall... 
aber versuchst.

Üblicherweise ist Ziel der Übung, nicht den kompletten, UI_Visitor_I 
definierenden Header und Sermon in X anderen Headern includen zu müssen, 
sondern lediglich in Modulen, welche den kompletten Typ kennen (müssen). 
Und / oder es wird damit vermieden, zyklische Klassenabhängigkeiten zu 
bekommen, denn für einen Incomplete Type benötigt man lediglich ein 
lapidares

struct Foo;
union Foo;
was-auch-immer Foo;

Implementier Show() also im adäquaten Modul nach Include der benötigten 
Klassendefnition — wo auch immer du die untergebracht hast.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Weiters kann der Anlass für diese Diagnostic der Umstieg auf eine neuere 
g++ Version sein, die bestimmte "ill-formed, no diagnostic required" 
Konstrukte nicht mehr toleriert.

Wie immer bei einem Umstieg auf eine neue Tool-Version, hat man 
natürlich alle zwischenzeitlich angesammelten Release-Notes und 
Porting-To Anleitungen studiert; hier insbesondere

https://gcc.gnu.org/gcc-7/porting_to.html

von Milhouse (Gast)


Lesenswert?

Mist, es geht...
Soll heißen, ich habs beseitigt und jetzt gehts, aber leider Abends mit 
nem dunen Kopf und weiß nicht mehr, was ich verändert habe...
Wäre sicher lehrreich gewesen.

von Jim M. (turboj)


Lesenswert?

Milhouse schrieb:
> Soll heißen, ich habs beseitigt und jetzt gehts, aber leider Abends mit
> nem dunen Kopf und weiß nicht mehr, was ich verändert habe...

Man sollte auch privat die Sourcen immer in einer Versionsverwaltung wie 
git oder Subversion vorhalten. Dann lassen sich solche fragen leicht mit 
einem diff beantworten...

von Milhouse (Gast)


Lesenswert?

>Man sollte auch privat die Sourcen immer in einer Versionsverwaltung
stimmt schon...
Aber ich hab mich dabei gefragt - wie haltet ihr das mit der "Commit 
Policy"?
Wahrscheinlich hätte ich den Stand eh nicht commited, weil er gar nicht 
compilierbar war...
Ich würde nur Sachen comitten, die wenigesten compilierbar sind. (?)

von Rolf M. (rmagnus)


Lesenswert?

Milhouse schrieb:
>>Man sollte auch privat die Sourcen immer in einer Versionsverwaltung
> stimmt schon...
> Aber ich hab mich dabei gefragt - wie haltet ihr das mit der "Commit
> Policy"?
> Wahrscheinlich hätte ich den Stand eh nicht commited, weil er gar nicht
> compilierbar war...
> Ich würde nur Sachen comitten, die wenigesten compilierbar sind. (?)

Für mich ist das nicht zwingend erforderlich. Wenn ich eine größere 
Änderung mache, bei der der Code über eine gewisse Zeit nicht 
compilierfähig ist, will ich nicht erst warten, bis alles komplett 
fertig ist, bevor ich meinen Commit mache. Denn ich will nicht, wenn ich 
nach 90% getaner Arbeit durch Schusseligkeit den frischen Code 
kaputtgemacht oder gar die bearbeiteten Files ganz gelöscht habe, 
nochmal komplett von vorne anfangen müssen.
Ich finde, es gibt nix schlimmeres als Code, den man sich mühsam 
erarbeitet hat, nach versehentlichem Vernichten ein zweites mal 
schreiben zu müssen.

Wenn das Repository nur für dich alleine ist, ist das ja auch nicht 
schlimm. Wenn man dagegen in der Gruppe arbeitet, ist das etwas anderes. 
Da brauchen die anderen eine compilierfähige Version im Repo. Da muss 
man sich dann was überlegen.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Angehängte Dateien:

Lesenswert?

"Merge branch 'asdfasjkfdlas/alkdjf' into sdkjfls-final"

von Bernd K. (prof7bit)


Lesenswert?

Rolf M. schrieb:
> Wenn das Repository nur für dich alleine ist, ist das ja auch nicht
> schlimm. Wenn man dagegen in der Gruppe arbeitet, ist das etwas anderes.
> Da brauchen die anderen eine compilierfähige Version im Repo. Da muss
> man sich dann was überlegen.

Dafür gibts Branches. Bevor man anfängt funktionierenden Code weiträumig 
umzugraben oder überhaupt irgendetwas etwas anfängt was länger dauern 
wird bis es fertig ist einfach schnell nen neuen Branch erzeugen. Dann 
kommt man keinem in die Quere.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Bernd K. schrieb:
> Dafür gibts Branches [...] schnell nen neuen Branch erzeugen.
> Dann kommt man keinem in die Quere.

Bestenfalls die Hydra beim Mergen :-)

von Rolf M. (rmagnus)


Lesenswert?

Bernd K. schrieb:
> Rolf M. schrieb:
>> Wenn das Repository nur für dich alleine ist, ist das ja auch nicht
>> schlimm. Wenn man dagegen in der Gruppe arbeitet, ist das etwas anderes.
>> Da brauchen die anderen eine compilierfähige Version im Repo. Da muss
>> man sich dann was überlegen.
>
> Dafür gibts Branches.

Ja, wenn man große Umbauten macht, schon. Aber es ist ja auch nicht Sinn 
der Sache, dass man für jede Änderung erst brancht, weil sie ggf. 
temporär mal nicht compilierbar ist.

von Bernd K. (prof7bit)


Lesenswert?

Rolf M. schrieb:
> Aber es ist ja auch nicht Sinn
> der Sache, dass man für jede Änderung erst brancht

Warum? Branchen kostet doch nichts, warum also damit geizen?

Man beschriftet einen Zettel und klebt ihn an die angefangene Arbeit. 
Den "das-funktioniert"-Zettel lässt man da kleben wo er ist. Wenn man 
fertig ist kann man überflüssige Zettel wieder wegwerfen.

Beschriftete Zettel die an Dingen kleben die von außen alle gleich 
aussehen aber nur eins davon ist zu benutzen sind Gold wert. Man kann 
gar nicht genug von diesen Aufklebern haben. Zum Glück kann man die 
Aufkleber bei git von einer kostenlosen Endlos-Rolle abreißen und 
überall hinkleben wo man will, nach Herzenslust, zum Nulltarif! Nennt 
sich Branch. Ungefähr so nützlich wie Dateinamen statt Nummern.

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.