Warum kannst du das '.' Nicht überladen? Operator in C ++?

78

Es wäre sehr nützlich, die überladen zu können. Operator in C ++ und geben Sie einen Verweis auf ein Objekt zurück.

Sie können überladen operator->und operator*aber nichtoperator.

Gibt es dafür einen technischen Grund?

Ferruccio
quelle
4
Können Sie ein Beispiel geben, wann Sie das '.' Überschreiben möchten? Operator?
Toon Krijthe
4
Im Allgemeinen ist der Anwendungsfall "intelligente Referenzen". Eine Art Proxy.
ddaa
2
@Gamecat: Lesen Sie diesen Vorschlag durch, um die Möglichkeit der Überlastung hinzuzufügen, operator.und operator.*es gibt einige Beispiele.
Mankarse
1
@ToonKrijthe Spaces um .sind erlaubt, also vielleicht ein kluger, aber entsetzlicher dynamischer Versand-Hack, der es erlaubt, Punktprodukte als auszudrücken matrix1 . matrix2.
MWCZ

Antworten:

62

Siehe dieses Zitat von Bjarne Stroustrup :

Operator . (Punkt) könnte im Prinzip mit der gleichen Technik wie für -> überladen werden. Dies kann jedoch zu Fragen führen, ob eine Operation für die Objektüberladung vorgesehen ist. oder ein Objekt, auf das verwiesen wird. Zum Beispiel:

class Y {
public:
    void f();
    // ...
};

class X {    // assume that you can overload .
    Y* p;
    Y& operator.() { return *p; }
    void f();
    // ...
};

void g(X& x)
{
    x.f();    // X::f or Y::f or error?
}

Dieses Problem kann auf verschiedene Arten gelöst werden. Zum Zeitpunkt der Standardisierung war nicht klar, welcher Weg der beste sein würde. Weitere Informationen finden Sie unter Das Design und die Entwicklung von C ++ .

Anton Gogolev
quelle
Vollständiges Zitat von TDaEoC ++ in meiner Antwort.
ddaa
15
Ich bin versucht, dies für Plagiate / Umfärbungen abzustimmen. Wenn Sie zitieren, zitieren Sie wörtlich, optimieren Sie nicht. Und verwenden Sie die Anführungszeichenformate.
Sebastian Mach
2
Das Beispiel ist nur eine Mehrdeutigkeit der Überlastungsauflösung, die auf eine sorgfältigere Programmierung hinweist (siehe: stackoverflow.com/questions/13554606/… ). Diese Situation sollte nicht als Grund dienen, nicht zu überlastenoperator .
slashmais
@slashmais Nein. Die Begründung von operator.ist eine explizite Parallele zu operator->. Und wie können Sie die Auflösung überladen?
Neugieriger
52

Stroustrup sagte, C ++ sollte eine erweiterbare, aber nicht veränderbare Sprache sein.

Der Punktoperator (Attributzugriff) wurde als zu nahe am Kern der Sprache angesehen, um eine Überladung zu ermöglichen.

Siehe Das Design und die Entwicklung von C ++ , Seite 242, Abschnitt 11.5.2 Smart References .

Als ich mich entschied, eine Überlastung des Bedieners zuzulassen ->, überlegte ich natürlich, ob der Bediener .ähnlich überlastet werden könnte.

Zu dieser Zeit hielt ich die folgenden Argumente für schlüssig: Wenn objes sich um ein Klassenobjekt handelt, obj.mhat dies eine Bedeutung für jedes Mitglied mder Klasse dieses Objekts. Wir versuchen, die Sprache nicht durch Neudefinition der integrierten Operationen veränderbar zu machen (obwohl diese Regel =aus dringenden Gründen und aus Gründen der Unregelmäßigkeit verletzt wird &).

Wenn wir das Überladen .einer Klasse zulassen Xwürden, könnten wir auf Xnormale Weise nicht auf Mitglieder von zugreifen . wir müssten einen Zeiger verwenden und ->, ->und &könnten auch neu definiert worden sein. Ich wollte eine erweiterbare Sprache, keine veränderliche.

Diese Argumente sind gewichtig, aber nicht schlüssig. Insbesondere schlug Jim Adcock 1990 vor, eine Überlastung des Bedieners . genau so zuzulassen , wie der Bediener ->ist.

Das "Ich" in diesem Zitat ist Bjarne Stroustrup. Sie können nicht maßgeblicher sein.

Wenn Sie C ++ wirklich verstehen wollen (wie in "Warum ist das so?"), Sollten Sie dieses Buch unbedingt lesen.

ddaa
quelle
28

Stroustrup hat eine Antwort auf diese Frage :

Operator . (Punkt) könnte im Prinzip mit der gleichen Technik wie für -> überladen werden. Dies kann jedoch zu Fragen führen, ob eine Operation für die Objektüberladung vorgesehen ist. oder ein Objekt, auf das verwiesen wird. Zum Beispiel:

class Y {
public:
    void f();
    // ...
};
class X {   // assume that you can overload .
    Y* p;
    Y& operator.() { return *p; }
    void f();
    // ...
};
void g(X& x)
{
    x.f();  // X::f or Y::f or error?
}

Dieses Problem kann auf verschiedene Arten gelöst werden. Zum Zeitpunkt der Standardisierung war nicht klar, welcher Weg der beste sein würde. Weitere Einzelheiten finden Sie D & E .

mfazekas
quelle
1
Siehe meinen Kommentar zu Antons Antwort
Slashmais
1

Es ist sehr leicht zu verstehen, wenn Sie den internen Mechanismus des Aufrufs von Operatorfunktionen durchlaufen. Angenommen, ein Klassenkomplex kann zwei Elemente r für den Realteil und i für den Imaginärteil haben. Sagen wir Komplex C1 (10,20), C2 (10,2) // wir nehmen an, dass es innerhalb der Klasse bereits einen Konstruktor mit zwei Argumenten gibt. Wenn Sie nun C1 + C2 als Anweisung schreiben, versucht der Compiler, die überladene Version des Operators + für eine komplexe Zahl zu finden. Jetzt nehmen wir an, dass ich + Operator überlade, also C1 + C2 intern übersetzt als c1.operator + (c2) Nehmen wir nun für die Zeit an, dass Sie 'überladen können.' Operator. Denken Sie nun an den folgenden Aufruf C1.disp () // Inhalt eines komplexen Objekts anzeigen Versuchen Sie nun, als interne Darstellung darzustellen C1.operator. (------) , völlig unordentliche Dinge erstellt. Das ist der Grund, warum wir nicht überladen können. Operator

Sourav Ghosh
quelle
1
Einige Leute sagen, intern übersetzt sollte nicht überladen anrufenoperator.
neugieriger Kerl