Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.net  
   

Die mobilen Seiten von c++.net:
https://m.c-plusplus.net

  
C++ Forum :: VCL (C++ Builder) ::  TFrame, ich möchte zusätzlich von Interface erben     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
5cript
Mitglied

Benutzerprofil
Anmeldungsdatum: 14.03.2009
Beiträge: 1948
Beitrag 5cript Mitglied 15:19:36 18.10.2016   Titel:   TFrame, ich möchte zusätzlich von Interface erben            Zitieren

Ich habe eine Klasse, die von TFrame erbt (erstellt mit Designer), diese bräuchte aber noch ein Interface von der sie erbt.
Aber wenn ich dem Interface, ein virtuellen Destruktor gebe, erhalte ich Linker Probleme.
Hab ich was falsch gemacht?


C++:
1
2
3
4
5
6
7
8
9
10
//---------------------------------------------------------------------------
class FrameInterface
{
public:
    // das hier einkommentieren -> Linker Fehler
    //virtual ~FrameInterface() __attribute__((fastcall)) = default;
 
    virtual void translate() = 0;
};
//---------------------------------------------------------------------------


C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//---------------------------------------------------------------------------
class THeaderOptionsFrame : public TFrame
                          , public FrameInterface
{
__published:    // Von der IDE verwaltete Komponenten
    TComboBox *HeaderLayer;
    TLabel *Label1;
    void __fastcall Label1Click(TObject *Sender);
private:    // Benutzer-Deklarationen
public:     // Benutzer-Deklarationen
    // ~THeaderOptionsFrame() __attribute__((fastcall)) = default;
    void translate() override;
    __fastcall THeaderOptionsFrame(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE THeaderOptionsFrame *HeaderOptionsFrame;
//---------------------------------------------------------------------------


"[ilink32 Fehler] Error: Nicht auflösbares externes '__fastcall _ZTh-696_THeaderOptionsFrame::~_ZTh-696_THeaderOptionsFrame()' referenziert von ***\WIN32\DEBUG\HEADER_OPTIONS.OBJ"
also "unresolved external..."

btw: ich kriege ich meine IDE (Berlin 10.1) nicht auf Englisch umgestellt, das Tool ignoriert mich einfach...

_________________
http://assets.amuniversal ....... 067f90134cb84005056a9545d


Zuletzt bearbeitet von 5cript am 15:20:50 18.10.2016, insgesamt 2-mal bearbeitet
asc
Mitglied

Benutzerprofil
Anmeldungsdatum: 12.01.2007
Beiträge: 6577
Beitrag asc Mitglied 08:46:55 19.10.2016   Titel:   Re: TFrame, ich möchte zusätzlich von Interface erben            Zitieren

5cript schrieb:
Ich habe eine Klasse, die von TFrame erbt (erstellt mit Designer)...
Hab ich was falsch gemacht?


Man kann mich gerne korrigieren, aber nach meiner Erkenntnis geht es nicht. Bei allen auf Delphi basierenden Klassen (VCL-Datentypen) scheiterte mein Versuch der Mehrfachvererbung.

Ich habe mir dann mit Templates ausgeholfen, die bei einer Klasse eine bestimmte Schnittstelle (Nicht im Sinne von Vererbung, sondern rein von der Methodensignatur her) erwartet hatten.

_________________
in theory there's no difference between theory and practice. in practice there is. (yogi berra)

In der Theorie gibt es kein Unterschied zwischen Theorie und Praxis. In der Praxis sehr wohl.


Zuletzt bearbeitet von asc am 08:48:18 19.10.2016, insgesamt 1-mal bearbeitet
Braunstein
Mitglied

Benutzerprofil
Anmeldungsdatum: 16.05.2002
Beiträge: 7059
Beitrag Braunstein Mitglied 09:55:26 19.10.2016   Titel:              Zitieren

Hallo,

Soviel wie ich weiß geht das auch nicht.
Ich behelfe mir so, dass ich von TFrame eine abstrakte Basisklasse ableite die das Interface implementiert. Von der wiederum leite ich dann die konkreten Frames ab.
DocShoe
Mitglied

Benutzerprofil
Anmeldungsdatum: 02.04.2008
Beiträge: 2607
Beitrag DocShoe Mitglied 15:49:32 19.10.2016   Titel:              Zitieren

Delphi unterstützt keine echte Mehrfachvererbung, man kann allerdings Interfaces (Klassen, die nur pure virtual Methoden besitzen) vererben:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
struct __declspec( uuid( "{EC2265C9-9A41-4E52-9D28-F67613A93A2D}" ) ) IPrintable
{
   virtual void print()   = 0;
   virtual void preview() = 0;
};
 
class MyFrame :
   public TFrame,
   public IPrintable
{
   ...
}


Über einen dynamic_cast kommt man da allerdings nicht wieder dran, sondern muss einige Verrenkungen übder das Delphi Typsystem machen (deshalb auch das __declspec( uuid (...) ).

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
template<typename DestT>
static DestT delphi_dynamic_cast( TObject* obj )
{
   if( obj )
   {
      TInterfaceEntry* Entry = obj->GetInterfaceEntry ( __uuidof( DestT ) );
     
      // funktioniert nur in 32bit Umgebungen, bei 64bit muss
      // man erst auf __int64 casten
      if( Entry ) return (DestT) ((int) obj + Entry->IOffset);
   }
   return nullptr;
}


Und so setzt man das ein:

C++:
IPrintable* Printable = delphi_dynamic_cast<IPrintable>( theFrame );
if( Printable )
{
   Printable->print();
   Printable->preview();
}

_________________
Die fünf häufigsten Anzeichen für Faulheit:
1.


Zuletzt bearbeitet von DocShoe am 15:50:14 19.10.2016, insgesamt 1-mal bearbeitet
5cript
Mitglied

Benutzerprofil
Anmeldungsdatum: 14.03.2009
Beiträge: 1948
Beitrag 5cript Mitglied 01:20:55 20.10.2016   Titel:              Zitieren

DocShoe schrieb:
...

Wow, das ist irgendwie eklig, aber sehr gut zu wissen.
Wenn ich das gleich gewusst hätte, hätte ich das so gemacht.

Braunstein schrieb:
...

Hmmm, da muss ich nochmal drüber nachdenken, wenn ich vor dem code sitze.

Ich hatte in der Zwischenzeit ein Workaround mit templates gebaut.

_________________
http://assets.amuniversal ....... 067f90134cb84005056a9545d
audacia
Mitglied

Benutzerprofil
Anmeldungsdatum: 05.02.2005
Beiträge: 4678
Beitrag audacia Mitglied 07:36:51 22.10.2016   Titel:              Zitieren

DocShoe schrieb:
Über einen dynamic_cast kommt man da allerdings nicht wieder dran, sondern muss einige Verrenkungen übder das Delphi Typsystem machen [...]
Verzeih, aber das ist ja furchtbar. Zum Glück geht das viel einfacher, nämlich mit interface_cast<>().

_________________
"Hey, it compiles! Ship it!"
C++Builder Pages · Typsichere Format-Strings
5cript
Mitglied

Benutzerprofil
Anmeldungsdatum: 14.03.2009
Beiträge: 1948
Beitrag 5cript Mitglied 15:29:14 24.10.2016   Titel:              Zitieren

Aber interface_cast verlangt, dass die Methoden QueryInterface, AddRef und Release implementiert sind, wie bei den Delphi Interfaces.

C++:
class THeaderOptionsFrame : public TFrame
                          , public TCppInterfacedObject<IOptionsFrame>

ist ja schon wieder quark, weil das ist wieder Mehrfachvererbung.
(Für folgenden code)
C++:
__interface __declspec(uuid("{5898CCAF-1EE4-4EB4-A785-48920E5E97A5}")) IOptionsFrame
    : public IInterface
{
    virtual void translate() = 0;
    virtual void setOwner(WikiElements::BasicElement* element) = 0;
};


Alternativ:
C++:
__interface __declspec(uuid("{5898CCAF-1EE4-4EB4-A785-48920E5E97A5}")) IOptionsFrame
{
    virtual void translate() = 0;
    virtual void setOwner(WikiElements::BasicElement* element) = 0;
};

resultiert in:
Zitat:
[bcc32c Fehler] systobj.h(264): kein Member mit Namen 'AddRef' in 'IOptionsFrame'

oder, dass THeaderOptionsFrame abstrakt ist, weil QueryInterface, AddRef und Release nicht implementiert sind.
bei Aufruf von:
C++:
auto* frame = element->getOptionsFrame(); // auto = THeaderOptionsFrame
if (frame)
{
    // Ich hatte es kurz nachgeprüft: interface_cast <IOptionsFrame*> ist falsch.
    interface_cast <IOptionsFrame> (frame)->translate();
    // ...
}



EDIT: Zur Zeit benutze ich die Verrenkung von DocShoe

_________________
http://assets.amuniversal ....... 067f90134cb84005056a9545d


Zuletzt bearbeitet von 5cript am 17:15:33 24.10.2016, insgesamt 5-mal bearbeitet
5cript
Mitglied

Benutzerprofil
Anmeldungsdatum: 14.03.2009
Beiträge: 1948
Beitrag 5cript Mitglied 17:30:41 24.10.2016   Titel:              Zitieren

Und renne gleich wieder gegen eine Wand, weil: ???
Habe jetzt ein weiteres Frame hinzugefügt und sobald ich das auch erben lasse vom Interface, dann erhalte ich untenstehenden Linkerfehler. -.-

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//---------------------------------------------------------------------------

#ifndef text_optionsH

#define text_optionsH
//---------------------------------------------------------------------------
#include "frame_interface.h"
#include "../element_fwd.h"

#include <System.Classes.hpp>

#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TTextOptionsFrame : public TFrame
                        , public IOptionsFrame
{
__published:    // Von der IDE verwaltete Komponenten
    TLabel *Label1;
private:    // Benutzer-Deklarationen
    bool translated_;
    WikiElements::Text* owner_;
public:     // Benutzer-Deklarationen
    void translate();
    void setOwner(WikiElements::BasicElement* owner);
    __fastcall TTextOptionsFrame(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TTextOptionsFrame *TextOptionsFrame;
//---------------------------------------------------------------------------
#endif


Zitat:
[ilink32 Fehler] Error: Nicht auflösbares externes 'TTextOptionsFrame::' referenziert von D:\DEVELOPMENT_IWS\WIKI-PROJECT\WIKI-EDITOR-VCL\WIN32\DEBUG\TEXT.OBJ


"externes 'TTextOptionsFrame::'" was soll das für nen Schmarn?

_________________
http://assets.amuniversal ....... 067f90134cb84005056a9545d
DocShoe
Mitglied

Benutzerprofil
Anmeldungsdatum: 02.04.2008
Beiträge: 2607
Beitrag DocShoe Mitglied 19:55:26 24.10.2016   Titel:              Zitieren

audacia schrieb:
DocShoe schrieb:
Über einen dynamic_cast kommt man da allerdings nicht wieder dran, sondern muss einige Verrenkungen übder das Delphi Typsystem machen [...]
Verzeih, aber das ist ja furchtbar. Zum Glück geht das viel einfacher, nämlich mit interface_cast<>().


Witzigerweise habe ich das von dir ;)

_________________
Die fünf häufigsten Anzeichen für Faulheit:
1.
audacia
Mitglied

Benutzerprofil
Anmeldungsdatum: 05.02.2005
Beiträge: 4678
Beitrag audacia Mitglied 12:41:35 25.10.2016   Titel:              Zitieren

5cript schrieb:
Aber interface_cast verlangt, dass die Methoden QueryInterface, AddRef und Release implementiert sind, wie bei den Delphi Interfaces.
Natürlich. Interface-Implementierung bei Delphi-Klassen wird nur für COM-Interfaces unterstützt, dein Interface muß also von IUnknown erben. Das Implementieren von Interfaces, die nicht von IUnknown erben, wird nicht unterstützt. (Gab es dazu nicht mal eine Compilerwarnung? Vielleicht hat es die nicht zum Clang-Compiler geschafft?)


5cript schrieb:
C++:
class THeaderOptionsFrame : public TFrame
                          , public TCppInterfacedObject<IOptionsFrame>

ist ja schon wieder quark, weil das ist wieder Mehrfachvererbung.
Genau. Aber TFrame erbt von TComponent, welches IInterface (= IUnknown) implementiert und also schon Implementationen der drei Methoden mitbringt.

Hier erweist es sich als hinderlich, daß Delphi anders mit Methodenüberschreibungen umgeht als C++. Folgendes Beispiel:

Delphi:
1
2
3
4
5
6
7
8
9
10
type
  TBase = class(TInterfacedObject)
    procedure Foo;
  end;
 
  IMyInterface = interface
    procedure Foo;
  end;
 
  TDerived = class(TBase, IMyInterface);

In Delphi benutzt TDerived die geerbte (nicht notwendig virtuelle!) Methode Foo() von TBase, um implizit IMyInterface.Foo() zu implementieren. In C++ passiert das nicht, hier mußt du explizit an die geerbte Methode verweisen. Für den Spezialfall der IUnknown-Methoden gibt es dafür das Makro INTFOBJECT_IMPL_IUNKNOWN():
C++:
class TTextOptionsFrame : public TFrame
                        , public IOptionsFrame
{
public:
    INTFOBJECT_IMPL_IUNKNOWN(TFrame)
    ...
};



schrieb:
"externes 'TTextOptionsFrame::'" was soll das für nen Schmarn?
Das ist die VMT zur Klasse TTextOptionsFrame. Den Linkerfehler verstehe ich gerade auch nicht; nimm doch mal TDUMP zur Hilfe, um nachzusehen, warum text.obj auf diese VMT verweist und warum text_options.obj das VMT-Symbol nicht exportiert.


DocShoe schrieb:
Witzigerweise habe ich das von dir ;)
Erwischt :D

Genaugenommen hast du es aber nicht von mir, sondern gemeinsam mit mir aus dieserm QC-Report, auf den ich in der fraglichen Diskussion vor 8 Jahren verlinkt hatte. Die bessere Lösung heißt TObject::GetInterface<>(), was ich in demselben Post auch erwähne.

Außerdem schrieb ich in demselben Thread drei Jahre später, daß es seit C++Builder XE den interface_cast<>() gibt, der Casts in beide Richtungen unterstützt und einem die ganzen haarigen Details abnimmt. Die Hoffnung, daß dadurch die furchtbaren Workarounds wieder verschwinden möchten, war wohl leichtfertig :)

_________________
"Hey, it compiles! Ship it!"
C++Builder Pages · Typsichere Format-Strings
5cript
Mitglied

Benutzerprofil
Anmeldungsdatum: 14.03.2009
Beiträge: 1948
Beitrag 5cript Mitglied 15:01:10 22.11.2016   Titel:              Zitieren

(Die späte Antwort, weil ich nur sporadisch an diesem Projekt arbeite)

Ich habe das mit der vtable Sache nicht "schnell genug" lösen können, deswegen habe ich den ganzen Kram über den Haufen geworfen und benutze jetzt ein Klassentemplate als Adapter.

_________________
http://assets.amuniversal ....... 067f90134cb84005056a9545d
5cript
Mitglied

Benutzerprofil
Anmeldungsdatum: 14.03.2009
Beiträge: 1948
Beitrag 5cript Mitglied 16:35:29 22.11.2016   Titel:              Zitieren

:O

jetzt wo ich alles umgebaut habe ist mir aufgefallen wo der Fehler her kam,
bzw ich wette es zu wissen.

C++:
void TTextOptionsFrame::translate();

war nicht aufgelöst. Das fehlte.

bescheuerte unverständliche Fehlermeldung....

_________________
http://assets.amuniversal ....... 067f90134cb84005056a9545d
C++ Forum :: VCL (C++ Builder) ::  TFrame, ich möchte zusätzlich von Interface erben   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.net ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info und www.c-plusplus.net enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.