Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Template-bastelei

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: [ 1 ] [ 2 ] > 3 < [ 4 ]
020
14.08.2003, 20:28 Uhr
virtual
Sexiest Bit alive
(Operator)


Ich denke, wir müssen nochmal klar machen, worum es geht: Du warst zu faul, eine Routine zu schreiben und willst jetzt ohne Rücksicht auf verluste eine neue Regel ausdenken. Diese Regel nimmt im Standard allenfalls einen Abschnitt ein. Aber was solls:

wegen 1:
Entweder nimmst Du eine Verletzung des Geheimnisprinzips in Kauf:

C++:
class A { /* wie von Dir beschrieben; */ }
class B: public A
{
    void myf(int x = i) { cout<<"Das private A::i hat den Wert"<<x<<std::endl;
};


Oder du mußt die Einschränkung in Kaufnehmen, daß nur protected/public members erlaubt sind. Ich denke, allein die so gewährte Initialisierung wird 3-5 Zusatzregeln machen, die die Sprache zu etwas machen würden, was deutlich schwerer verständlich ist.
Von der Sinnhaftigkeit mal völlig abgesehen: Wenn Du Dich auf this beschränkst, wären ja auch folgende Konstruktionen denkbar:

C++:
class A {
public:
int getI() const { }
void f(int = this->getI()) :kotz: {}
};



wegen 2:
Mit einem sich selbst an den Konstruktor übergeben ist ziemlich sinnlos, deshalb macht dies nicht so wahnsinnig sinn. Dies ist ein Beispiel dafür, daß in diesem Fall ziemlich viel mit nur halb initialisierten Objekten gemacht werden kann:

C++:
class B;
class A
{
public: A(B* b) { b->doBmethod(); };
};
class B
{
    int x;
public:
    B(B* b=this) :A(b) { x = 0; }
    void doBmethod();
};


Kann man zu stehen, wie man will. Öffnet aber Tür und Tor für Fehler, würde man also ggf. Unterbinden, macht die Sprache so oder so schwerer.
Das Beispiel mit der Mehrfachvererbung zeigt, daß this zwei Instanzen von A hat., wer soll woher wissen, welches von beiden genommen wird? - Soll man es verbieten? - Oder nur zulassen, wenn D einen Konvertierungsoperator nach A hat? Das würde wieder eine Ausnahmeregel provozieren.

wegen 3:
Das ist extrem willkürlich und für mich nicht nachvollziehbar.

Sagen wirs mal so: Wenn du ein C++ gefunden hast, was das kann, was du willst, sag es mir bitte: Ich weiß dann was ich meiden muß.

Tut mir leid, aber ich kann es wirklich nicht verstehen und bin auch ein wenig erschrocken, wie man halbwegs straight forward Regeln in irgendein kunterbuntes Mischmasch wandeln will. Wie man den lex+yacc Bedient weißt Du ja -> roll your own.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
021
15.08.2003, 09:57 Uhr
0xdeadbeef
Gott
(Operator)


Moment, moment. Der Reihe nach.

1.1 Das Geheimnisprinzip wird nicht verletzt. Aufrufe wie

C++:
class A { int i; };
struct B : public A { int get(int x = i) { return x; } };

wären ebenso unzulässig wie

C++:
class A { int i; }
struct B : public A { int getI() { return i; } };


1.2 Ja, solche Konstrukte wären dann legal. Das ist mit ein Clou an der Sache.

2. Der Code funzt schon nicht, weil zum Zeitpunkt der Deklaration von A B::doMethod nicht bekannt ist und B nicht von A abeleitet ist. Ein ähnlicher Code:

C++:
class B;
void do_something(B*);

class A {
public:
  A(B* b) { do_something(b); }
};
class B : public A {
  friend void do_something(B*);
  int x;
public:
  B() : A(this) { x = 0; }
};

void do_something(B* b) { b->x = 0; }
int main() { B b; }

kompiliert allerdings schon jetzt ohne Probleme, und diese ambiguous call-Probleme hast du auch jetzt schon, was den Konstruktor angeht, sogar ohne Mehrfachvererbung. Der Code

C++:
struct A { A(){} };
struct B : public A { };
struct C : public B { C() : A() { } };

kompiliert nicht. Fehlermeldung:

Code:
a.cpp: In constructor `C::C()':
a.cpp:3: error: type `struct A' is not a direct base of `C'


3. Du hast drei überlagernde Kontexte. Wenn der Parameter übergeben wurde, nimmt er den. Ist das nicht der Fall, sucht er sich die Sachen, die er zum konstruieren braucht, aus dem Klassenkontext, und wenn er sie da nicht findet, im globalen. Wenn er sie überhaupt nicht findet --> Compilerfehler. Ich sehe nicht, was daran willkürlich ist, diese Scoping-Geschichte läuft doch so ziemlich überall auf die selbe Weise.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 15.08.2003 um 09:57 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
022
15.08.2003, 10:30 Uhr
virtual
Sexiest Bit alive
(Operator)


Ich habs mal vereinfacht und stelle Dir viermal die gleiche Frage:

Zitat:
0xdeadbeef postete
Moment, moment. Der Reihe nach.

1.1 Das Geheimnisprinzip wird nicht verletzt. Aufrufe wie

C++:
class A { int i; };
struct B : public A { int get(int x = i) { return x; } };

wären ebenso unzulässig wie


Na toll: also habe ich ein Sprachkonstrukt, welches mir Zugriff nur auf public Member Variablen erlaubt. Dumm nur, daß public Members aus OO Sicht ziemlicher unsinn sind und zu vermeiden sind. Weißt Du weshalb: Wegen geheimnisprinzip! Machen solche Dinge Deiner Meinung nach die Sprache einfacher?


Zitat:

2. Der Code funzt schon nicht, weil zum Zeitpunkt der Deklaration von A B::doMethod nicht bekannt ist und B nicht von A abeleitet ist. Ein ähnlicher
Code:


Witzbold, ich hätte von Dir schon die Transferleistung erwartet, daß man die Implementation von A in einer getrennten Datei hält, dies aber - um das Posting nicht ausufern zu lassen - bleiben läßt.
Klar geht das auch jetzt, wie du gezeigt hast. Aber daß es geht, bedeutet ja nicht, daß es sinnvoll ist. Meine Meinung dazu ist, daß der Code dadurch noch Fehleranfälliger wird. Zumindestens müßt man sagen: this Als Defaultargument ist erlaubt, aber hüte Dich davor es in ctoren zu tun. Machen solche Dinge Deiner Meinung nach die Sprache einfacher?



Zitat:

und diese ambiguous call-Probleme hast du auch jetzt schon, was den Konstruktor angeht, sogar ohne Mehrfachvererbung. Der Code

C++:
struct A { A(){} };
struct B : public A { };
struct C : public B { C() : A() { } };

kompiliert nicht. Fehlermeldung:

Code:
a.cpp: In constructor `C::C()':
a.cpp:3: error: type `struct A' is not a direct base of `C'



Das ist nicht der Punkt: Dein Fehler ist ein ganz simpler C++ Fehler, der Kommt, wenn man nicht direkt den Konstruktor der directen Baisklasse aufruft. Das hat überhaput nix mit der Situation zu tun, die ich beschrieben habe:
Wenn Du Dir das Ursprüngliche Beispiel mit der Mehrfachvererbung anschaust, wirst Du feststellen, daß eine Instanz der Klasse D zwei Instanzen von Klasse A enthält (Siehe Lehrbuch bzgl. Mehrfachvererbung.)
Der Defaultparameter mit (A* = this) Kann daher nicht funktionieren => Ausnahmeregelung erforderlich. Machen solche Dinge Deiner Meinung nach die Sprache einfacher?



Zitat:

3. Du hast drei überlagernde Kontexte. Wenn der Parameter übergeben wurde, nimmt er den. Ist das nicht der Fall, sucht er sich die Sachen, die er zum konstruieren braucht, aus dem Klassenkontext, und wenn er sie da nicht findet, im globalen. Wenn er sie überhaupt nicht findet --> Compilerfehler. Ich sehe nicht, was daran willkürlich ist, diese Scoping-Geschichte läuft doch so ziemlich überall auf die selbe Weise.



Leider geht dann aber so was:

C++:
const int i;

class
{
public:
     void f(int x = i);
public: // Verletzung geheimnisprinzip, hatten wir ja schon
     int i;
};


So, wie C++ aufgebaut ist, muß Der Compiler als Defaultparameter das globale i nehmen. Dh das Beispiel uinetrscheidet sich von:

C++:
const int i;

class
{
public: // Verletzung geheimnisprinzip, hatten wir ja schon
     int i;
public:
     void f(int x = i);
};


Ziemlicher Schrott würde ich sagen. Machen solche Dinge Deiner Meinung nach die Sprache einfacher?
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
023
15.08.2003, 10:39 Uhr
virtual
Sexiest Bit alive
(Operator)


Noch was zu den Überlegungen, daß

C++:
X* i;
X* f(X* =i);


Nichts anderes sei als

C++:
X* i;
X* f(X*);
X* f() {return f(i); };


Das ist nicht ganz korrekt. eigentlich ist obiges zu so sehen:

C++:
X* i;
X* f(X*);
X* f() {return f(::i); }; // Beachte Scoperesultion


Das ist meiner Meinung nach das, worum wir und hier streiten.

Auch solche Sachen:

C++:
struct
{
   X(X*& = this) { ... }
};


Müssten gezwungenermassen in der Weiteren Diskussion eigentlich

C++:
struct X
{
   X(X*[b]const[/b]& = this) { ... }
};


Lauten, um nicht komplett die const correctness zu unterlaufen.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 15.08.2003 um 11:56 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
024
15.08.2003, 10:49 Uhr
0xdeadbeef
Gott
(Operator)


Weia. Inzwischen hätt ich jedem anderen wahrscheinlich sowas wie "Du willst es nicht verstehen, oder?" an den Kopf geworfen. Es geht wirklich nur ums Scoping. Also:
1.1
Illegal:

C++:
class A {
  int i;
};
class B: public A {
  public int get(int x = i) { return x; }
};


Begründung: Wenn der Parameter nicht gegeben wird, sucht sich B::get im Klassenkontext von b ein i zusammen. Da A::i private ist, hat B keinen Zugriff auf A::i und kann es nicht als Default-Parameter benutzen.
Legal:

C++:
class A {
  int i;
public:
  int get(int x = i) { return x; }
};


Denn A::get sucht sich im Klassenkonext von A ein i zusammen. A hat Zugriff auf A::i, also geht das.
Ebenfalls legal:

C++:
class A {
protected:
  int i;
};
class B : public A {
public:
  int get(int x = i) { return x; }
};


Weil B auf A::i Zugriff hat. Easy.

2.1 Dass etwas nicht immer sinnvoll ist, heißt nicht, das es verboten sein sollte. Der Code

C++:
char *p = 0;
*p = 'A';


ist auch nicht sinnvoll, aber legal. Dadurch wird es aber nicht sinnlos, dass man einen Pointer auf Null setzen oder seinen Inhalt mit etwas füllen kann. Genauso wird es nicht sinnlos, this in der Deklaration eines Default-Parameters zu verwenden, nur weil man damit sinnlosen Code schreiben kann.

2.2 Ach so, darauf willst du hinaus. Auf dieselbe Problematik kommst du aber mit

C++:
class D : public B, public C {
  D() { A *a = this; }
};


und genauso sollte man es auch behandeln.

3. Genauso behandeln wie

C++:
int i;

class A {
public:
  void do_something() { i = 3; }
  int i;
};


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
025
15.08.2003, 10:53 Uhr
0xdeadbeef
Gott
(Operator)


Was das zweite Posting angeht: Deine Code-Beispiele haben keinen wirklichen Zusammenhang. Mal ist i X*, mal int, und dazu kommt, dass du eine void-Funktion einen int zurückgeben lässt. So wie ich das meinte, ist es das gleiche wie

C++:
X *i;
void f(X*);
void f() { return f(i); }



Was die const-Korrektheit angeht, da hast du recht. Aber das ist so oder so so.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
026
15.08.2003, 11:02 Uhr
virtual
Sexiest Bit alive
(Operator)


Lassen wir es mal dabei bewenden. Du kannst mich nicht überzeugen. Ich dich offenbar auch nicht. Ich würde diese Sprache nicht mögen, aus Gründen, die du nicht verstehen willst/kannst, andersrum verstehe ich nicht, weshalb man klare Regeln aufweichen will, um lokale Variablen in globalen Kontexten aufrufen zu können (und dabei noch ohne rot zu werden von "Scoping" zu sprechen: alle Achtung!).
Den Aspekt der "Vereinfachung" sehe ich halt nicht, eher den des Chaoses.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
027
15.08.2003, 11:05 Uhr
virtual
Sexiest Bit alive
(Operator)


Sorry für die Fehler im 2. Post. Corrected. Ich hoffe jetzt ists klarer
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
028
15.08.2003, 11:35 Uhr
0xdeadbeef
Gott
(Operator)


Ich sehe nicht, wo du da einen globalen Kontext siehst. Die Methode, die den Default-Parameter nimmt, wird in der Klasse deklariert. Sofern sie nicht static deklariert ist, haben wir damit einen Instanzkontext, und den kann man dann auch als Scope hernehmen. Und wie du sicher weißt, binden lokale Kontexte stärker als Instanzkontexte genauso stark wie Klassenkontexte (weil die sich nicht ins Gehege kommen können) stärker als der globale Kontext. Ich sehe nicht, wo da irgendwelche Inkonsistenzen entstehen. In Java gehen noch viel schönere Sachen, und die Sprache hat den Ruf sehr sauber und einfach zu sein. Nimm zum beispiel das hier:

C++:
class A {
  protected class B {
    public void bla() { ++i; }
  }

  protected int i;
  protected B b;

  public A() { b = new B(); }
  public void increaseI() { B.bla(); }
}


Und gerade sowas wie dieses Beispiel ist unglaublich praktisch. Eins meiner Lieblingsfeatures an Java.

Was das korrigierte zweite Posting angeht: Das ist immer noch falsch. Was du meinst ist

C++:
void f() { return f(i); }

bzw.

C++:
void f() { return f(::i); }

--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 15.08.2003 um 11:37 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
029
15.08.2003, 12:05 Uhr
virtual
Sexiest Bit alive
(Operator)


habe das zweite Post updated. Jetzt stimmts aber wirklich.

Du tust Java unrecht: Es hat keine Defaultargumente. Es hat einfach ein anderes - aber konsistentes - Konzept von Protectionlevels.

Was das Scoping angeht: this is eine lokale Variable innerhalb einer Methode. Du gehst quasi ganz nebenbei davon aus, daß man nun this im übergeordneten Scope - nämlich Klasse - anwenden können sollte. Das weicht ein klares Scopekonzept auf. Für meinen Geschmack für einen ziemlich billigen Effekt.

Ich habe ausserdem - ohne es direkt widerlegt bekommen zu sehen - angeführt, daß man an Stelle der ebenfalls sehr klaren Regel bzgl Defaultargument nun eine neue Einfügen müsste, die Ausnahmeregeln erfordert (zB Mehrfachvererbung ist ein 100%iger Kandidat).

Es mag immer sein, daß man irgendwelche Features gerne hätte, aber ich habe nicht das Gefühl gewonnen, daß sie die Sprache wirklich bereichern würden (die in diesem Thread diskutierten), sondern eher verwässern und mit mehr Ausnahmeregelungen auch schwerer verständlich.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: [ 1 ] [ 2 ] > 3 < [ 4 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: