<?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[Liskov Substitution Principle ist unbequem]]></title><description><![CDATA[<p>Hallo Freunde.</p>
<p>In <a href="http://www.objectmentor.com/resources/articles/lsp.pdf" rel="nofollow">diesem</a> Artikel wird das Liskov Substitution Principle beschrieben. Das laesst sich wie folgt zusammenfassen (aus <a href="http://www.eventhelix.com/RealtimeMantra/Object_Oriented/liskov_substitution_principle.htm" rel="nofollow">http://www.eventhelix.com/RealtimeMantra/Object_Oriented/liskov_substitution_principle.htm</a> geklaut):</p>
<blockquote>
<p>In class hierarchies, it should be possible to treat a specialized object as if it were a base class object.</p>
</blockquote>
<p>Ein Beispiel zur Veranschaulichung:</p>
<pre><code class="language-cpp">void f(Base* b) {
    //use b
}
</code></pre>
<p>Laut LSP soll es moeglich sein, den Parametertyp Base durch einen beliebigen, von Base abgeiteten, Datentyp zu ersetzen, ohne dass das Unerwartete passiert (beispielsweise eine Exception geworfen wird).</p>
<p>Ich verstehe zwar diese Problematik, die LSP zu vermeiden versucht, aber bei genauerer Betrachtung erscheint mir die Einhaltung sehr unbequem.</p>
<p>Ich erklaere mein Problem mal an einem anderen Beispiel: Ich habe ein paar abgeleitete Klassen, eine Hierarchie von vielen 'Datentypen' einer Datenbank. Es existiert eine abstrakte Basisklasse Data_type, von der sich andere Dinge ableiten, wie Zahlen, Texte und so:</p>
<pre><code class="language-cpp">class Data_type {};

class Number : public Data_type {};

vieles mehr
</code></pre>
<p>Soweit, sogut.<br />
Das Problem ist: Es soll eine allgemeine Tabelle geben (einspaltig), welche alle Datentypen aufnehmen kann. Weiterhin soll es eine Tablle geben, die *nur* Zahlen aufnehmen soll.</p>
<pre><code class="language-cpp">class Table {
public:
    virtual void insert(Data_type&amp;)=0;
};

class Data_types_table : public Table {
public:
    void insert(Data_type&amp;);// gemaess LSP implementiert
};

Fortsetzung folgt
</code></pre>
<p>Die rein virtuelle Table::insert-Funktion sagt anhand des Data_type&amp;-Parameters eigentlich alles aus: &quot;Fuege Datentypen ein. Also alle ohne Ausnahme&quot;. Das hat LSP gut rueber gebracht. Klienten, die eine Table-Referenz benutzen, erwarten, wenn sie einen Datentyp ueber diese Referenz einfuegen, dass der Datentyp auch wirklich eingefuegt wird, da diese Aussage quasi im Parametertyp dokumentiert ist. Das ist logisch und der Gedanke gefaellt mir.</p>
<p>Aber das bringt meiner Meinung nach nicht nur Unbequemlichkeiten mit sich, sondern 'verunstaltet' auch das Design. Denn: Was ist eigentlich, wenn ich jetzt eine Tabelle einfuehren will, die nur Zahlen aufnimmt? Das wuerde dem LSP klar widersprechen:</p>
<pre><code class="language-cpp">class Numbers_table : public Table { 
public:
    void insert(Data_type&amp; dt) {
        //pruefe, ob dt eine Zahl ist... wenn nicht, wirf eine Exception
        //sonst normal fortfahren
    }
};
</code></pre>
<p>Numbers_table::insert verhaelt sich wohl nicht so, wie Klienten das von einer Table::insert erwarten. Kein guter Stil?</p>
<p>Der Autor da oben wuerde mein Problem in etwa so regeln:</p>
<pre><code class="language-cpp">class Numbers_table { // man beachte die Unabhaengigkeit
public:
    virtual void insert(Number&amp;)=0; //keine Probleme mehr mit unerwartetem Verhalten
};
</code></pre>
<p>Das ist sogar eine viel besser Loesung, als sich mit bad_cast rumzuschlagen... wenn dadurch nur nicht das Problem mit der Zusammenfassung entstehen wuerde: Ich kann jetzt nicht mehr ohne weiteres schreiben, dass eine 'Datenbank' 'Tabellen' enthaelt. Nein, ich muss jetzt mindestens zwei Datenbanken haben, die jeweils 'normale Tabellen' (was sind aus der Sicht einer abstrakten Klasse eigentlich schon normale?*) und Tabellen mit Zahlen aufnehmen koennen. Nur eine einzige Datenbank haben, das ist mit diesem Design, dass auch Tabellen mit Zahlen unterztuetzen soll, nicht mehr moeglich. Und ueberhaupt: fuer jeden neuen Datentyp koennte ich eine neue Tabelle wollen, die eigens dazu da ist, um Objekte dieses Typs aufzunehmen. Aber fuer jede neue Tabelle eine neue Datebank? Das ist doch zum Kotzen, oder nicht?</p>
<p>Ich kann etwas Albernes machen:</p>
<pre><code class="language-cpp">class Abstract_table { 
    virtual ~Abstract_table()=0;
//total leer, oder zumindest kein insert mehr, da insert(?)
};

und alle erben oeffentlich von Abstract_table
</code></pre>
<p>Und dann doch eine, und nur eine, Datenbankklasse kreieren, um Typen von Abstract_table aufzunehmen, aber das nuetzt mir herzlich wenig, da keine grundlegende Funktionalitaet in Abstract_table festgelegt ist und ich sowieso nicht weiss, welcher tatsaechliche Typ dahinter steckt.</p>
<p>* Gilt das LSP auch fuer abstrakte Klassen? Wenn ich das LSP benutze, moechte ich konsequent bleiben. Also gilt das LSP gefaelligst auch fuer abstrakte Klassen und das Problem besteht weiterhin. (Ich erwaehne diese Moeglichkeit nur, weil abstrakte Klassen, speziell Protokoll-Klassen sich von der Implementation trennen; eine Pre-condition liegt aber schon im Parametertyp fest bzw. ist die Bedingung selber, die, wenn eingehalten, die Funktion fein laufen laesst.)</p>
<p>Was wenn Typen speziell dafuer entworfen wurden, den dynamischen Typ hinter einem Objekt zu ermitteln? Zum Beispiel der &quot;Muellsortierer&quot; aus &quot;Thinking in C++ 2nd edition&quot;? Der Sortierer ist dazu ausgelegt, verschiedene Trash-Sorten in geeignete Muelleimer zu sortieren, mittels RTTI. Entweder hat der Autor LSP ignoriert, oder absichtlich so entworfen? Oder er hatte keine Ahnung? Ich hab auch keine Ahnung, ist jetzt auch egal.</p>
<p>Also, ich hoffe auf hilfreiche Antworten, um das aus der Welt zu schaffen.<br />
Gibt es eine bessere Loesung, als auf LSP zu verzichten oder viele Datenbanken zu haben?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/126229/liskov-substitution-principle-ist-unbequem</link><generator>RSS for Node</generator><lastBuildDate>Mon, 24 Aug 2026 14:48:08 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/126229.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 13 Nov 2005 04:05:43 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Liskov Substitution Principle ist unbequem on Sun, 13 Nov 2005 04:39:47 GMT]]></title><description><![CDATA[<p>Hallo Freunde.</p>
<p>In <a href="http://www.objectmentor.com/resources/articles/lsp.pdf" rel="nofollow">diesem</a> Artikel wird das Liskov Substitution Principle beschrieben. Das laesst sich wie folgt zusammenfassen (aus <a href="http://www.eventhelix.com/RealtimeMantra/Object_Oriented/liskov_substitution_principle.htm" rel="nofollow">http://www.eventhelix.com/RealtimeMantra/Object_Oriented/liskov_substitution_principle.htm</a> geklaut):</p>
<blockquote>
<p>In class hierarchies, it should be possible to treat a specialized object as if it were a base class object.</p>
</blockquote>
<p>Ein Beispiel zur Veranschaulichung:</p>
<pre><code class="language-cpp">void f(Base* b) {
    //use b
}
</code></pre>
<p>Laut LSP soll es moeglich sein, den Parametertyp Base durch einen beliebigen, von Base abgeiteten, Datentyp zu ersetzen, ohne dass das Unerwartete passiert (beispielsweise eine Exception geworfen wird).</p>
<p>Ich verstehe zwar diese Problematik, die LSP zu vermeiden versucht, aber bei genauerer Betrachtung erscheint mir die Einhaltung sehr unbequem.</p>
<p>Ich erklaere mein Problem mal an einem anderen Beispiel: Ich habe ein paar abgeleitete Klassen, eine Hierarchie von vielen 'Datentypen' einer Datenbank. Es existiert eine abstrakte Basisklasse Data_type, von der sich andere Dinge ableiten, wie Zahlen, Texte und so:</p>
<pre><code class="language-cpp">class Data_type {};

class Number : public Data_type {};

vieles mehr
</code></pre>
<p>Soweit, sogut.<br />
Das Problem ist: Es soll eine allgemeine Tabelle geben (einspaltig), welche alle Datentypen aufnehmen kann. Weiterhin soll es eine Tablle geben, die *nur* Zahlen aufnehmen soll.</p>
<pre><code class="language-cpp">class Table {
public:
    virtual void insert(Data_type&amp;)=0;
};

class Data_types_table : public Table {
public:
    void insert(Data_type&amp;);// gemaess LSP implementiert
};

Fortsetzung folgt
</code></pre>
<p>Die rein virtuelle Table::insert-Funktion sagt anhand des Data_type&amp;-Parameters eigentlich alles aus: &quot;Fuege Datentypen ein. Also alle ohne Ausnahme&quot;. Das hat LSP gut rueber gebracht. Klienten, die eine Table-Referenz benutzen, erwarten, wenn sie einen Datentyp ueber diese Referenz einfuegen, dass der Datentyp auch wirklich eingefuegt wird, da diese Aussage quasi im Parametertyp dokumentiert ist. Das ist logisch und der Gedanke gefaellt mir.</p>
<p>Aber das bringt meiner Meinung nach nicht nur Unbequemlichkeiten mit sich, sondern 'verunstaltet' auch das Design. Denn: Was ist eigentlich, wenn ich jetzt eine Tabelle einfuehren will, die nur Zahlen aufnimmt? Das wuerde dem LSP klar widersprechen:</p>
<pre><code class="language-cpp">class Numbers_table : public Table { 
public:
    void insert(Data_type&amp; dt) {
        //pruefe, ob dt eine Zahl ist... wenn nicht, wirf eine Exception
        //sonst normal fortfahren
    }
};
</code></pre>
<p>Numbers_table::insert verhaelt sich wohl nicht so, wie Klienten das von einer Table::insert erwarten. Kein guter Stil?</p>
<p>Der Autor da oben wuerde mein Problem in etwa so regeln:</p>
<pre><code class="language-cpp">class Numbers_table { // man beachte die Unabhaengigkeit
public:
    virtual void insert(Number&amp;)=0; //keine Probleme mehr mit unerwartetem Verhalten
};
</code></pre>
<p>Das ist sogar eine viel besser Loesung, als sich mit bad_cast rumzuschlagen... wenn dadurch nur nicht das Problem mit der Zusammenfassung entstehen wuerde: Ich kann jetzt nicht mehr ohne weiteres schreiben, dass eine 'Datenbank' 'Tabellen' enthaelt. Nein, ich muss jetzt mindestens zwei Datenbanken haben, die jeweils 'normale Tabellen' (was sind aus der Sicht einer abstrakten Klasse eigentlich schon normale?*) und Tabellen mit Zahlen aufnehmen koennen. Nur eine einzige Datenbank haben, das ist mit diesem Design, dass auch Tabellen mit Zahlen unterztuetzen soll, nicht mehr moeglich. Und ueberhaupt: fuer jeden neuen Datentyp koennte ich eine neue Tabelle wollen, die eigens dazu da ist, um Objekte dieses Typs aufzunehmen. Aber fuer jede neue Tabelle eine neue Datebank? Das ist doch zum Kotzen, oder nicht?</p>
<p>Ich kann etwas Albernes machen:</p>
<pre><code class="language-cpp">class Abstract_table { 
    virtual ~Abstract_table()=0;
//total leer, oder zumindest kein insert mehr, da insert(?)
};

und alle erben oeffentlich von Abstract_table
</code></pre>
<p>Und dann doch eine, und nur eine, Datenbankklasse kreieren, um Typen von Abstract_table aufzunehmen, aber das nuetzt mir herzlich wenig, da keine grundlegende Funktionalitaet in Abstract_table festgelegt ist und ich sowieso nicht weiss, welcher tatsaechliche Typ dahinter steckt.</p>
<p>* Gilt das LSP auch fuer abstrakte Klassen? Wenn ich das LSP benutze, moechte ich konsequent bleiben. Also gilt das LSP gefaelligst auch fuer abstrakte Klassen und das Problem besteht weiterhin. (Ich erwaehne diese Moeglichkeit nur, weil abstrakte Klassen, speziell Protokoll-Klassen sich von der Implementation trennen; eine Pre-condition liegt aber schon im Parametertyp fest bzw. ist die Bedingung selber, die, wenn eingehalten, die Funktion fein laufen laesst.)</p>
<p>Was wenn Typen speziell dafuer entworfen wurden, den dynamischen Typ hinter einem Objekt zu ermitteln? Zum Beispiel der &quot;Muellsortierer&quot; aus &quot;Thinking in C++ 2nd edition&quot;? Der Sortierer ist dazu ausgelegt, verschiedene Trash-Sorten in geeignete Muelleimer zu sortieren, mittels RTTI. Entweder hat der Autor LSP ignoriert, oder absichtlich so entworfen? Oder er hatte keine Ahnung? Ich hab auch keine Ahnung, ist jetzt auch egal.</p>
<p>Also, ich hoffe auf hilfreiche Antworten, um das aus der Welt zu schaffen.<br />
Gibt es eine bessere Loesung, als auf LSP zu verzichten oder viele Datenbanken zu haben?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/916519</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/916519</guid><dc:creator><![CDATA[endline]]></dc:creator><pubDate>Sun, 13 Nov 2005 04:39:47 GMT</pubDate></item><item><title><![CDATA[Reply to Liskov Substitution Principle ist unbequem on Sun, 13 Nov 2005 08:11:22 GMT]]></title><description><![CDATA[<p>meines Wissens sagt das lsp ganz klar aus: eine abgeleitete Klasse darf nie härtere Beschränkungen haben, als eine Basisklasse. Das ist sehr sinnvoll.</p>
<p>hier mal ein anschauliches Beispiel:</p>
<pre><code class="language-cpp">//Basisklasse
class Rechteck{
    private:
        int x,y;
    public:
        Rechteck(int x,int y);
        virtual ~Rechteck();
        virtual void setX(int x);
        virtual void setY(int y);
};

//verwendung
Rechteck* r=new Rechteck(3,4);
r-&gt;setX(5);
r-&gt;setY(4);
</code></pre>
<p>Die Basisklasse sollte Klar sein. Nun ist aber auch ein Quadrat ein rechteck...leiten wir mal ab</p>
<pre><code class="language-cpp">class Quadrat:public Rechteck{
    public:
        Quadrat(int x);//man braucht nurnoch eine seitenlänge
        virtual void setX(int x);//vererbt durch rechteck
        virtual void setY(int y);
};
Rechteck* r= new Quadrat(3,4);
r-&gt;setX(5);
r-&gt;setY(4);//und nu?
</code></pre>
<p>wie du siehst, erlaubt rechteck, dass x und y unterschiedliche werte haben, während bei einem Quadrat beide werte gleich sein müssen. Im endeffekt darf man also Quadrat nicht von Rechteck erben lassen, weil das doof wird. Das Interface vereinbart gewisse anforderungen mit dem Benutzer, an die er sich zu halten hat-von den zusätzlichen vereinbarungen in der abgeleiteten Klassen kann er nichts wissen.</p>
<p>nach dem LSP würde man wohl deinen Ansatz leicht verändern:</p>
<pre><code class="language-cpp">class Data_type {
     public:
         //gibt an, welche art von daten gespeichert sind
         virtual int getType()=0;
};
class Table {
public:
    virtual void insert(Data_type&amp;)=0;
    //gibt an, welcher Datentyp gespeichert werden darf
    virtual int getType()=0;
};
</code></pre>
<p>nun sind die zusätzlichen beschränkungen teil der Basisklasse, und das LSP ist wieder erfüllt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/916527</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/916527</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Sun, 13 Nov 2005 08:11:22 GMT</pubDate></item><item><title><![CDATA[Reply to Liskov Substitution Principle ist unbequem on Sun, 13 Nov 2005 09:49:55 GMT]]></title><description><![CDATA[<p>alle generalisierungen sind falsch.</p>
<p>natürlich muß man auch mal abweichen, wenn das prinzip zu unpraktisch ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/916549</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/916549</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Sun, 13 Nov 2005 09:49:55 GMT</pubDate></item><item><title><![CDATA[Reply to Liskov Substitution Principle ist unbequem on Sun, 13 Nov 2005 09:53:58 GMT]]></title><description><![CDATA[<p>Aber nicht in diesem Fall. otze hat vollkommmen Recht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/916552</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/916552</guid><dc:creator><![CDATA[Ringding]]></dc:creator><pubDate>Sun, 13 Nov 2005 09:53:58 GMT</pubDate></item><item><title><![CDATA[Reply to Liskov Substitution Principle ist unbequem on Sun, 13 Nov 2005 11:39:50 GMT]]></title><description><![CDATA[<p>Ringding schrieb:</p>
<blockquote>
<p>Aber nicht in diesem Fall. otze hat vollkommmen Recht.</p>
</blockquote>
<pre><code class="language-cpp">//gibt an, welcher Datentyp gespeichert werden darf 
    virtual int getType()=0;
</code></pre>
<p>aber er hat mit nem schlimmeren designfehler sein prinzip verteidigt, als wo was der bruch des prinzips gebracht hätte. des fehler wird klar, wenn man versucht, solchige klasse zu verwenden und die switch-orgie einen in den wahnsinn treibet.</p>
<p>ok, der fehler war vorgabe. &quot;Es existiert eine abstrakte Basisklasse Data_type, von der sich andere Dinge ableiten, wie Zahlen, Texte und so&quot;. könnte sein, daß man nach dieser vorgabe einfach nicht mehr sinnvoll (im feierlichen c++-stil) reparieren kann.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/916614</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/916614</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Sun, 13 Nov 2005 11:39:50 GMT</pubDate></item><item><title><![CDATA[Reply to Liskov Substitution Principle ist unbequem on Sun, 13 Nov 2005 11:44:24 GMT]]></title><description><![CDATA[<p>volkard schrieb:</p>
<blockquote>
<p>Ringding schrieb:</p>
<blockquote>
<p>Aber nicht in diesem Fall. otze hat vollkommmen Recht.</p>
</blockquote>
<pre><code class="language-cpp">//gibt an, welcher Datentyp gespeichert werden darf 
    virtual int getType()=0;
</code></pre>
<p>aber er hat mit nem schlimmeren designfehler sein prinzip verteidigt, als wo was der bruch des prinzips gebracht hätte. des fehler wird klar, wenn man versucht, solchige klasse zu verwenden und die switch-orgie einen in den wahnsinn treibet.</p>
</blockquote>
<p>wo siehst du da switch orgien? Die kommen doch erst rein, wenn du anhand von Data_type::getType herausfinden willst, in welche Tabelle etwas reingepackt werden muss. Aber an der Stelle hätte wohl sogut wie jede Lösung einen üblen knackpunkt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/916621</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/916621</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Sun, 13 Nov 2005 11:44:24 GMT</pubDate></item><item><title><![CDATA[Reply to Liskov Substitution Principle ist unbequem on Sun, 13 Nov 2005 13:04:19 GMT]]></title><description><![CDATA[<p>Richtig übel wäre es ja erst wenn es keine Invarianz bei den Parametertypen geben würde.<br />
Wenn das LSP erfüllt sein soll müssten die Parameter eines Subtyps kontravariant zu denen des Supertyps sein.<br />
Dieses Verhalten ist aber unnatürlich.<br />
In nem aktuellen Kurs(in dem es allerdings über Design by Contract geht,welches aber dir gleichen Probleme bei Vererbung/Substituierbarkeit mit sich bringt)<br />
ist nen Beispiel mit ner parallelen Klassenhierarchie gegeben.<br />
Es gibt ne abstrakte Klasse Printer die eine Methode print hat,welche als Parameter ein Exemplar,der ebenfalls abstrakten Klasse,Document hat.<br />
Printer hat die konkreten Subtypen Plotter und LinePrinter.<br />
Document hat die konkreten Subtypen Text und Drawing.<br />
Plotter können nur Objekte vom Typ Drawing drucken und LinePrinter nur Text.<br />
Eine natürliche Modelierung wäre es jetzt wenn man die Parametertypen in Plotter und LinePrinter redefinieren würde.Damit würde man allerdings das LSP<br />
verletzen weil die Parametertypen sich ja höchstens in die allgemeinere Richtung entwickeln dürften.<br />
In C++ muss man sich darüber ja keine Gedanken machen.....gibt´s nich und fertig.<br />
Aber der arme Bertrand Meyer kann schon seit Jahren nicht richtig schlafen weil das Typsystem von Eiffel und sein Design by Contract Konzept sich ansich<br />
wiedersprechen <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>
<p>Ich denke da sollte man nicht allzu &quot;wissenschaftlich&quot; dran gehen und jedesmal für das konkrete Problem die angemessenste Lösung suchen.</p>
<p>MfG Spacelord</p>
]]></description><link>https://www.c-plusplus.net/forum/post/916691</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/916691</guid><dc:creator><![CDATA[Spacelord]]></dc:creator><pubDate>Sun, 13 Nov 2005 13:04:19 GMT</pubDate></item><item><title><![CDATA[Reply to Liskov Substitution Principle ist unbequem on Sun, 13 Nov 2005 13:32:05 GMT]]></title><description><![CDATA[<p>Hallo,<br />
imo ist das hier die Ausprägung des klassischen &quot;Ein Foo ist ein Ding, also ist eine Liste von Foo eine Liste von Dingen&quot;-Denkfehlers. Das wirkt zwar auf den ersten Blick logisch, stimmt aber spätestens bei der Einfügeoperation nicht mehr. In eine Liste von Foo kann man nur Foos reintun. In eine Liste von Dingen aber auch Atom-U-Boote. Behandelst du nun eine Liste von Foo als Liste von Dingen, dann ist der dritte Weltkrieg wieder ein Stück näher.<br />
LSP sorgt hier nur dafür, dass der Denkfehler explizit wird. Imo ist das eine gute Sache und es wäre falsch, hier einfach LSP zu ignorieren.</p>
<p>Eine Tabelle die nur Nummern aufnehmen kann ist nunmal keine Tabelle die alle Datentypen aufnehmen kann. Auch nicht, wenn Nummer eine Spezialisierung von Datentyp ist. Die Java-Leute lösen das mit ihren &quot;bounded wildcard generics&quot; (i.e. list&lt;? extends Super&gt; bzw. list&lt;? super Super&gt;). Was sich imo sehr nach &quot;hack-hack-hack&quot; anfühlt.</p>
<p>In C++ würde ich mich erstmal fragen, ob Table (bzw. dessen insert-Methode) wirklich polymorph sein muss. Vielleicht reicht es ja, wenn Lesen polymorph ist.</p>
<pre><code class="language-cpp">class Table {
public:
    // Methoden außer insert
};

template &lt;class BaseType&gt;
class MutableTable : public Table {
public:
    void insert(const BaseType&amp; t);

};

typedef MutableTable&lt;DataType&gt; GenericTable;
typedef MutableTable&lt;Number&gt; NumberTable;
</code></pre>
<p>Das ist in den vielen Fällen völlig ausreichend, da die Datenquelle meistens sowieso streng-getypt ist, also weiß, welche Art von Daten sie liefert. Wenn meine Datenquelle weiß, dass sie Numbers liest, demzufolge also bereits von Number abhängig ist, dann kann sie auch MutableTable&lt;Number&gt; verwenden ohne, dass dadurch neue Abhängigkeiten entstehen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/916717</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/916717</guid><dc:creator><![CDATA[HumeSikkins]]></dc:creator><pubDate>Sun, 13 Nov 2005 13:32:05 GMT</pubDate></item><item><title><![CDATA[Reply to Liskov Substitution Principle ist unbequem on Sun, 13 Nov 2005 22:34:20 GMT]]></title><description><![CDATA[<p>Danke.<br />
Ich werd mal eine Weile darueber medieteren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/916866</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/916866</guid><dc:creator><![CDATA[endline]]></dc:creator><pubDate>Sun, 13 Nov 2005 22:34:20 GMT</pubDate></item></channel></rss>