<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[&amp;quot;Klassentyp&amp;quot; übergeben?]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich suche eine Möglichkeit eine Klasse (nicht das Objekt) zu übergeben / speichern.</p>
<p>Beispiel:</p>
<p>struct MyStruct {<br />
string Ident ;<br />
class(?) : Klasse;<br />
} MS;</p>
<p>..<br />
MS[0].Name = '123F';<br />
MS[0].Klasse = CMeineKlasse;<br />
..</p>
<p>um dann folgendes machen zu können:</p>
<p>..<br />
a = *CBasisKlasse ;<br />
a= (*CBasisKlasse) new MS[0].Klasse;<br />
..</p>
<p>Unter Delphi geht das mit &quot;class of&quot; und class als Typ.<br />
Wie ist das unter C++ / G++ ?</p>
<p>Danke für hilfreiche Antworten.</p>
<p>Gruß<br />
NewBee</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/282359/quot-klassentyp-quot-übergeben</link><generator>RSS for Node</generator><lastBuildDate>Sun, 23 Aug 2026 06:34:21 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/282359.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 18 Feb 2011 14:59:15 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Fri, 18 Feb 2011 14:59:15 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich suche eine Möglichkeit eine Klasse (nicht das Objekt) zu übergeben / speichern.</p>
<p>Beispiel:</p>
<p>struct MyStruct {<br />
string Ident ;<br />
class(?) : Klasse;<br />
} MS;</p>
<p>..<br />
MS[0].Name = '123F';<br />
MS[0].Klasse = CMeineKlasse;<br />
..</p>
<p>um dann folgendes machen zu können:</p>
<p>..<br />
a = *CBasisKlasse ;<br />
a= (*CBasisKlasse) new MS[0].Klasse;<br />
..</p>
<p>Unter Delphi geht das mit &quot;class of&quot; und class als Typ.<br />
Wie ist das unter C++ / G++ ?</p>
<p>Danke für hilfreiche Antworten.</p>
<p>Gruß<br />
NewBee</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2022856</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2022856</guid><dc:creator><![CDATA[NewBee2]]></dc:creator><pubDate>Fri, 18 Feb 2011 14:59:15 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Fri, 18 Feb 2011 15:00:44 GMT]]></title><description><![CDATA[<p>Nachtrag</p>
<p>die Qualifizierung mit [0] ist hier ein versehen.<br />
Nachher soll es ein array of struct werden!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2022857</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2022857</guid><dc:creator><![CDATA[NewBee2]]></dc:creator><pubDate>Fri, 18 Feb 2011 15:00:44 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Fri, 18 Feb 2011 15:06:04 GMT]]></title><description><![CDATA[<p>Erstell eine virtuelle Funktion.</p>
<pre><code class="language-cpp">virtual MyClass *MyClass::Create()
{
 return new MyClass;
}

// [...]
a = X.Create();
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2022860</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2022860</guid><dc:creator><![CDATA[dfgd]]></dc:creator><pubDate>Fri, 18 Feb 2011 15:06:04 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Fri, 18 Feb 2011 15:17:36 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>danke für die Antwort,</p>
<p>aber</p>
<p>a) müsste dazu MyClass nicht bereits instaniziert sein? (oder eine Klassenfunktion)<br />
b) müsste ich das für alle Unterklassen meinr Basisklasse ableiten.</p>
<p>Gibt es keine Möglichkeit, den von mir beschriebenen Weg zu gehen?</p>
<p>Gruß<br />
NewBee</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2022866</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2022866</guid><dc:creator><![CDATA[NewBee2]]></dc:creator><pubDate>Fri, 18 Feb 2011 15:17:36 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Fri, 18 Feb 2011 15:20:07 GMT]]></title><description><![CDATA[<p>abstract factory pattern</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2022867</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2022867</guid><dc:creator><![CDATA[af]]></dc:creator><pubDate>Fri, 18 Feb 2011 15:20:07 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Fri, 18 Feb 2011 15:26:10 GMT]]></title><description><![CDATA[<p>af schrieb:</p>
<blockquote>
<p>abstract factory pattern</p>
</blockquote>
<p>Hat m.E. nix mit Klassenübergabe zu tun. factory pattern kapseln nur die Erzeugung. In dieser stehe ich dann ja vor dem gleichen Problem.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2022871</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2022871</guid><dc:creator><![CDATA[NewBee2]]></dc:creator><pubDate>Fri, 18 Feb 2011 15:26:10 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Fri, 18 Feb 2011 15:40:22 GMT]]></title><description><![CDATA[<p>Vielleicht sowas?</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
Base* Create()
{
    return new T;
}

std::map&lt;int, Base* (*)()&gt; map;
map[0] = &amp;Create&lt;MyClass&gt;;
map[1] = &amp;Create&lt;OtherClass&gt;;
</code></pre>
<p>Bei fortlaufenden Indizes kannst du auch <code>std::vector</code> nehmen.</p>
<p>P.S.: Bitte hör mit diesem <a href="http://www.c-plusplus.net/forum/p2005233#2005233" rel="nofollow">grausamen C-Präfix</a> auf.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2022881</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2022881</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Fri, 18 Feb 2011 15:40:22 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Fri, 18 Feb 2011 15:53:41 GMT]]></title><description><![CDATA[<p>NewBee2 schrieb:</p>
<blockquote>
<p>Unter Delphi geht das mit &quot;class of&quot; und class als Typ.<br />
Wie ist das unter C++ / G++ ?</p>
</blockquote>
<p>C++ unterstützt Metaklassen, Klassenreferenzen und (virtuelle) Klassenmethoden nicht, insbesondere keine virtuellen Konstruktoren. Du mußt dir irgendeinen Workaround mithilfe von Templates ausdenken. Etwa so:</p>
<p>(Nicht erschrecken, es ist etwas wild; laß dich einen Moment darauf ein, dann leuchtet ein, wieso es sinnvoll ist):</p>
<pre><code class="language-cpp">template &lt;class I&gt; struct MetaInterface {};
template &lt;class I, class C&gt; struct MetaClass : MetaInterface &lt;I&gt; {};

struct BaseObject { ... }; // irgendeine Basisklase
template &lt;&gt;
    struct MetaInterface&lt;BaseObject&gt;
{
    virtual BaseObject* create (SomeType someParams) = 0; // quasi virtueller Konstruktor
    virtual bool supports (SomeType someCondition) = 0; // quasi virtuelle Klassenmethode
};
typedef MetaInterface&lt;BaseObject&gt; BaseInterface; // quasi &quot;class of&quot;

template &lt;class C&gt; struct MetaClass&lt;Base, C&gt; : MetaInterface&lt;Base&gt;
{
        // Standardimplementation des virtuellen Konstruktors
        // (man beachte die Kovarianz des Rückgabewertes)
    virtual C* create (SomeType someParams) { return new C (someParams); }
        // Standardimplementation der virtuellen Klassenfunktion
    virtual bool supports (SomeType someCondition) { return false; }
};
MetaClass&lt;BaseObject, BaseObject&gt; BaseClass;

struct DefaultObject : public BaseObject
{
    DefaultObject (SomeType someParams) { ... }
};
MetaClass&lt;BaseObject, DefaultObject&gt; DefaultClass; // benutzt obige Standardimplementation

struct SpecializedObject : public BaseObject
{
    SpecializedObject (bool somethingElse, SomeType someParams) { ... }
};
template &lt;&gt;
    struct MetaClass&lt;BaseObject, SpecializedObject&gt; : MetaClass&lt;BaseObject, BaseObject&gt;
{
        // Spezialisierung des virtuellen Konstruktors für SpecializedObject
    virtual SpecializedObject* create (SomeType someParams) { return new SpecializedObject (false, someParams); }
        // Spezialisierung der Klassenfunktion
    virtual bool supports (SomeType someCondition) { ... }
};
MetaClass&lt;BaseObject, SpecializedObject&gt; SpecializedClass;

BaseInterface* myClassReference = &amp;SpecializedClass;
BaseObject* myObject = myClassReference-&gt;create (someParams);
</code></pre>
<p>Disclaimer: Code ist ungetestet.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2022887</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2022887</guid><dc:creator><![CDATA[audacia]]></dc:creator><pubDate>Fri, 18 Feb 2011 15:53:41 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Fri, 18 Feb 2011 18:16:44 GMT]]></title><description><![CDATA[<p>Ich verstehe gerade nicht, warum das abstract factory pattern nicht genau das macht, was du willst?</p>
<pre><code class="language-cpp">a = *CBasisKlasse ;
a= (*CBasisKlasse) new MS[0].Klasse;
</code></pre>
<p>würde dann so aussehen:</p>
<pre><code class="language-cpp">a = MS[0].Factory-&gt;Create();
</code></pre>
<p>wobei die Factories halt alle ein Objekt, das von CBasisKlasse abgeleitet wurde, zurückgeben (oder besser gesagt einen Zeiger darauf).</p>
<p>Was genau soll das hier bedeuten?</p>
<pre><code class="language-cpp">a = *CBasisKlasse ;
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2022963</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2022963</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 18 Feb 2011 18:16:44 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Fri, 18 Feb 2011 18:27:25 GMT]]></title><description><![CDATA[<p>An Audacias Beispiel würde ich jetzt mal kritisieren, dass man vor lauter templates, Metas, Specializeds, Bases gar nicht mehr sieht, dass das dasselbe ist wie ein simples virtual factory pattern, nur mit templates, Metas, Specializeds und Bases.<br />
Aber wahrscheinlich übersehe ich da gerade auch etwas...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2022966</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2022966</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 18 Feb 2011 18:27:25 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Fri, 18 Feb 2011 19:23:32 GMT]]></title><description><![CDATA[<p>Warum überhaupt immer Klassen und virtuelle Funktionen mit möglichst viel Boilerplate-Code benutzen, wenn sich virtuelle Konstruktoren übersichtlich und mit einer Zeile Code pro abgeleiteter Klasse implementieren lassen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2023009</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2023009</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Fri, 18 Feb 2011 19:23:32 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Fri, 18 Feb 2011 19:38:31 GMT]]></title><description><![CDATA[<p>Ich kann dir gerade nicht folgen, Nexus.</p>
<p>Aber wie wär's mit []() -&gt; Base* { return new Derived; }<br />
Ziemlich kurz! <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2023017</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2023017</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Fri, 18 Feb 2011 19:38:31 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Sat, 19 Feb 2011 13:03:47 GMT]]></title><description><![CDATA[<p>Decimad schrieb:</p>
<blockquote>
<p>Ich verstehe gerade nicht, warum das abstract factory pattern nicht genau das macht, was du willst?</p>
</blockquote>
<p>Weil Klassenreferenzen in Delphi viel mehr sind als nur irgendwelche Factories.</p>
<p>Decimad schrieb:</p>
<blockquote>
<p>An Audacias Beispiel würde ich jetzt mal kritisieren, dass man vor lauter templates, Metas, Specializeds, Bases gar nicht mehr sieht, dass das dasselbe ist wie ein simples virtual factory pattern</p>
</blockquote>
<p>Offenbar habe ich dich tatsächlich soweit verwirrt, daß du nicht erkanntest, daß es <em>nicht</em> dasselbe ist <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Mein Beispiel ist so umfangreich, weil ich damit versucht habe, einige der Möglichkeiten von Klassenreferenzen in Delphi nachzubilden. Und wie du schon festgestellt hast, ist es auch ein gutes Argument dafür, stattdessen einfach Delphi zu benutzen, wo man sich nicht explizit mit &quot;Metas, Specializeds und Bases&quot; herumschlagen muß. Aber ich will es gerne nochmal im Einzelnen vorstellen.</p>
<p>Ich beginne mal mit dem Klassenreferenzen-Standardbeispiel: den Dateiformaten. Wir haben eine abstrakte Basisklasse <code>Image</code> , zu der es etwa die Unterklassen <code>Bitmap</code> , <code>PNGImage</code> und <code>JPEGImage</code> geben könnte. Das sieht zunächst so aus:</p>
<pre><code>// Delphi:
type
  TImage = class
  public
    constructor CreateCopy(Image: TImage); overload; virtual; abstract;
    constructor CreateFromStream(Stream: TStream); overload; virtual; abstract;
    procedure SaveToStream(Stream: TStream); virtual; abstract;
  end;
  TBitmap = class (TImage)
  public
    constructor CreateCopy(Image: TImage); override;
    constructor CreateFromStream(Stream: TStream); override;
    procedure SaveToStream(Stream: TStream); override;
  end;
</code></pre>
<pre><code class="language-cpp">// C++:
class Image
{
public:
    virtual void saveToStream (std::ostream&amp; stream) = 0;
};
class Bitmap
{
public:
    Bitmap (Image* image);
    Bitmap (std::istream&amp; stream);
    virtual void saveToStream (std::ostream&amp; stream);
};
</code></pre>
<p>Die handelsübliche Benutzung verläuft in Delphi und C++ gleichermaßen (Exceptionsicherheit ignorieren wir jetzt mal):</p>
<pre><code>function LoadBitmapFromFile (const FileName: String): TImage;
var
  Stream: TStream;
begin
  Stream := ...;
  Result := TBitmap.CreateFromStream (SomeFileStream);
end;
</code></pre>
<pre><code class="language-cpp">Image* loadBitmapFromFile (const std::string&amp; fileName)
{
    std::fstream stream (...);
    return new Bitmap (stream);
}
</code></pre>
<p>So einfach ist es natürlich meistens nicht; wir wollen ja mehrere Dateiformate unterstützen. Unsere Laderoutine soll in der Lage sein, das Dateiformat zu berücksichtigen. In Delphi:</p>
<pre><code>type
  TImageClass = class of TImage;

function LoadImageFromFile (const FileName: String; ImageClass: TImageClass): TImage;
var
  Stream: TStream;
begin
  Stream := ...;
  Result := ImageClass.CreateFromStream (SomeFileStream);
end;

{ bescheuertes Anwendungsbeispiel }
function LoadBitmapFromFile (const FileName: String): TBitmap;
begin
  Result := LoadImageFromFile (FileName, TBitmap) as TBitmap; { Hier wird eine Klasse als Argument übergeben! }
end;
</code></pre>
<p>In C++ könnten wir das natürlich mit einem Factory-Template nachbilden:</p>
<pre><code class="language-cpp">typedef Image* (ImageStreamFactory) (std::istream&amp; stream);
template &lt;class T&gt;
    Image* imageStreamFactory (std::istream&amp; stream)
{
    return new T (stream);
}

Image* loadImageFromFile (const std::string&amp; fileName, ImageStreamFactory factory)
{
    std::fstream stream (...);
    return factory (stream);
}

    // bescheuertes Anwendungsbeispiel
Bitmap* loadBitmapFromFile (const std::string&amp; fileName)
{
    return &amp;dynamic_cast&lt;Bitmap&amp;&gt; (*loadImageFromFile (fileName, imageStreamFactory&lt;Bitmap&gt;));
}
</code></pre>
<p>Nun läßt sich der Bildtyp aber meist dem Dateinamen entnehmen; es sollte möglich sein, die Auswahl des Graphikformats zu automatisieren. Wir brauchen so etwas wie ein globales Verzeichnis aller verfügbaren Graphikformate, aus denen unsere Funktion selbst auswählen kann. In C++ wäre das mit obigen Factories folgendermaßen lösbar:</p>
<pre><code class="language-cpp">class ImageRegistry
{
public:
    void registerImageFactoryForFileExt (const std::string&amp; fileExt, ImageStreamFactory factory);
    ImageStreamFactory getByFileExt (const std::string&amp; fileExt);
};
ImageRegistry theRegistry;

void registerKnownImageClasses (void) // muß beim Start der Anwendung aufgerufen werden
{
    theRegistry.registerImageFactoryForFileExt (&quot;.bmp&quot;, imageStreamFactory&lt;Bitmap&gt;);
    ...
}

Image* loadImageFromFile (const std::string&amp; fileName)
{
    std::fstream stream (...);
    return (theRegistry-&gt;getByFileExt (extractFileExt (fileName))) (stream);
}
</code></pre>
<p>Wir möchten aber außerdem noch eine generische Speicherroutine haben, die automatisch die richtige Dateiendung hinzufügt. Die Dateiendung ist ja nicht ein Spezifikum unserer <code>ImageRegistry</code> ; sie gehört zur Klasse <code>Image</code> dazu und sollte auch <code>Image</code> -Objekten bekannt sein. Also nehmen wir etwas Redundanz in Kauf und spendieren <code>Image</code> noch eine Methode, die die Dateiendung zurückgibt:</p>
<pre><code class="language-cpp">class Image
{
...
    virtual std::string getFileExt (void) = 0;
};

...

std::string Bitmap::getFileExt (void)
{
    return &quot;.bmp&quot;;
}

void saveImageToFile (Image* image, const std::string&amp; fileName)
{
    std::string fullName = fileName + image-&gt;getFileExt ();
    std::fstream stream (...);
    image-&gt;saveToStream (stream);
}
</code></pre>
<p>Eigentlich ist die Dateiendung aber eine Eigenschaft der <em>Klasse</em> <code>Image</code> , nicht eines <em>Objektes</em> von diesem Typ; wir wollen auch <code>Bitmap::getFileExt()</code> schreiben können. Aber dazu müßte <code>getFileExt()</code> statisch und virtuell zugleich sein.</p>
<p>Tatsächlich geht das in Delphi:</p>
<pre><code>type
  TImage = class
  ...
    class function GetFileExt: String; virtual; abstract; // &quot;class function&quot; entspricht statischer Methode
  end;

  TClassRegistry = class
  public
    function FindFirstClass&lt;T&gt; (Predicate: TPredicate&lt;T&gt;): T;
    function FindClasses&lt;T&gt; (Predicate: TPredicate&lt;T&gt;): TArray&lt;T&gt;;
  end;

var
  ClassRegistry: TClassRegistry;

function FindImageClassByFileExt (const AFileExt: String): TImageClass;
begin
  Result := ClassRegistry.FindFirstClass&lt;TImageClass&gt; (
    function (TheClass: TImageClass): Boolean
    begin
      Result := TheClass.GetFileExt = AFileExt; { GetFileExt() ist eine Klassenfunktion und kann ohne Instanz aufgerufen werden.
                                                  Zugleich ist es virtuell; was zurückgegeben wird, hängt davon ab, ob TheClass
                                                  auf TBitmap, TJPEGImage oder TPNGImage verweist. (So wie übliche Zeiger
                                                  Objektzeiger sind, ist TheClass ein Klassenzeiger.) }
    end);
end;

function LoadImageFromFile (const FileName: String): TImage;
var
  Stream: TStream;
begin
  Stream := ...;
  Result := FindImageClassByFileExt (ExtractFileExt (FileName)).CreateFromStream (Stream);
end;

procedure SaveImageToFile (Image: TImage; const FileName: String);
var
  FullName: String;
  Stream: TStream;
begin
  FullName := FileName + Image.GetFileExt; { Ebenso kann GetFileExt natürlich für Objekte aufgerufen werden; es verhält
                                             sich auch hier wie eine virtuelle Funktion, abhängig vom Typ des Objektes. }
  Stream := ...;
  Image.SaveToStream (Stream);
end;
</code></pre>
<p>Wie man sieht, ist hier die <code>ImageRegistry</code> zu einer allgemeineren <code>ClassRegistry</code> geworden; es ist nicht nötig, daß der Registrierungsmechanismus von den Dateiendungen weiß oder überhaupt auf von <code>Image</code> abgeleitete Klassen beschränkt ist. Es gibt außerdem keine Redundanz bezüglich der Dateiendung: sie wird von der virtuellen Klassenmethode <code>GetFileExt()</code> zurückgegeben und muß nicht beim Registrieren der Klasse zusätzlich angegeben werden. Außerdem muß die Klasse nicht von Hand registriert werden; die <code>ClassRegistry</code> ist von selbst in der Lage, alle im Projekt definierten Klassen zu finden (das ist allerdings ein anderes Thema).</p>
<p>Es gibt noch viele andere Möglichkeiten, von den Klassenreferenzen Gebrauch zu machen. Vielleicht möchten wir ein Duplikat einer Graphik im selben Format erstellen können:</p>
<pre><code>function CreateDuplicate (Image: TImage): TImage;
begin
  Result := TImageClass (Image.ClassType).CreateCopy (Image);
end;
</code></pre>
<p>Oder wir beugen uns der Einsicht, daß Dateiendungen im realen Leben nicht immer mit dem Inhalt übereinstimmen müssen, und implementieren die Erkennung von Dateiendungen auf Signaturbasis (z.B. beginnen Bitmap-Dateien immer mit den Bytes &quot;BM&quot;, bei PNG-Dateien steht &quot;\x89PNG\x0D\x0A\x1A\x0A&quot; etc.):</p>
<pre><code>type
  TImage = class
  ...
    class function SignatureMatches (Stream: TStream): Boolean; virtual; abstract;
  end;

...

class function TBitmap.SignatureMatches(Stream: TStream): Boolean;
var
  Sig: array[0..1] of AnsiChar;
begin
  if Stream.Size &lt; 2 then
    Exit (False);
  Stream.ReadBuffer (Sig, 2);
  Stream.Position := Stream.Position - 2;
  Result := (Sig[0] = 'B') and (Sig[1] = 'M');
end;

function FindImageClassBySignature (Stream: TStream): TImageClass;
begin
  ImageClasses := ClassRegistry.FindFirstClass&lt;TImageClass&gt; (
    function (TheClass: TImageClass): Boolean
    begin
      Result := TheClass.SignatureMatches (Stream);
    end);
end;
</code></pre>
<p>Natürlich reichen die Factories vollkommen aus, wenn der OP nur einen einzigen virtuellen Konstruktor nachbilden will. Aber es ist vielleicht klargeworden, warum man schon zu ein paar &quot;Metas&quot; und &quot;Specializeds&quot; greifen muß, wenn man Klassenreferenzen in C++ nachbilden will.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2023251</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2023251</guid><dc:creator><![CDATA[audacia]]></dc:creator><pubDate>Sat, 19 Feb 2011 13:03:47 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Sat, 19 Feb 2011 22:12:54 GMT]]></title><description><![CDATA[<p>lol, ich hab noch nie ernsthaft gehört, dass irgendwer einen Vorteil von Delphi ggü. C++ argumentieren möchte *duck und wegrenn*</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2023446</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2023446</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Sat, 19 Feb 2011 22:12:54 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Sun, 20 Feb 2011 03:36:59 GMT]]></title><description><![CDATA[<p>Man sollte normalerweise nicht versuchen bestimmte Features von Sprache X in Sprache Y nachzubilden.<br />
Sondern lieber versuchen das was man eigentlich erreichen will in Y so zu implementieren wie es mit Y gut umzusetzen ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2023504</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2023504</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Sun, 20 Feb 2011 03:36:59 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Sun, 20 Feb 2011 11:52:17 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p>Man sollte normalerweise nicht versuchen bestimmte Features von Sprache X in Sprache Y nachzubilden.<br />
Sondern lieber versuchen das was man eigentlich erreichen will in Y so zu implementieren wie es mit Y gut umzusetzen ist.</p>
</blockquote>
<p>Sehe ich auch so. Ich bin seinerzeit nach einigem Experimentieren davon abgerückt, den oben erwähnten Workaround produktiv zu verwenden. Wenn ich Klassenreferenzen brauche, nehme ich Delphi.</p>
<p>Wenn man in C++ nur einen einzigen virtuellen Konstruktor braucht, nimmt man eben Factories. Und wenn man so etwas wie mein Graphikformat-Beispiel machen möchte, wird man wahrscheinlich auch lieber auf die genaue Nachbildung verzichten und stattdessen zwei Klassenhierarchien parallel pflegen:</p>
<pre><code class="language-cpp">class Image;
class ImageType
{
public:
    virtual Image* createCopy (Image* rhs) = 0;
    virtual Image* createFromStream (std::istream&amp; stream) = 0;
    virtual std::string getFileExt (void) = 0;
    virtual bool signatureMatches (std::istream&amp; stream) = 0;
};

class Image
{
public:
    virtual void saveToStream (std::ostream&amp; stream) = 0;
    virtual ImageType&amp; getType (void) = 0;
};

class Bitmap;
class BitmapType
{
public:
    virtual Bitmap* createCopy (Image* rhs);
    virtual Bitmap* createFromStream (std::istream&amp; stream);
    virtual std::string getFileExt (void) { return &quot;.bmp&quot;; }
    virtual bool signatureMatches (std::istream&amp; stream);
};
BitmapType bitmapType;

class Bitmap
{
public:
    Bitmap (Image* image);
    Bitmap (std::istream&amp; stream);
    virtual void saveToStream (std::ostream&amp; stream);
    virtual BitmapType&amp; getType (void) { return bitmapType; }
};
</code></pre>
<p>Die Nachteile sind gut tragbar, solange man nicht überbordenden Gebrauch von diesen expliziten &quot;Typklassen&quot; macht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2023623</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2023623</guid><dc:creator><![CDATA[audacia]]></dc:creator><pubDate>Sun, 20 Feb 2011 11:52:17 GMT</pubDate></item><item><title><![CDATA[Reply to &amp;quot;Klassentyp&amp;quot; übergeben? on Sun, 20 Feb 2011 12:10:18 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/8276">@audacia</a>: <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
<p>Und danke für den Exkurs über Klassenreferenzen, tut meinem Tellerrand gut!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2023635</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2023635</guid><dc:creator><![CDATA[fdfdg]]></dc:creator><pubDate>Sun, 20 Feb 2011 12:10:18 GMT</pubDate></item></channel></rss>