Im Cfront-C++-Modus verhält sich der Compiler kompatibel zu Cfront-C++ V3.0, d.h. er unterstützt eine Reihe entsprechender Funktionsmerkmale und spezifischer Eigenschaften. Der Cfront-C++-Modus wird unterstützt, damit existierender Code, der Erweiterungen der Cfront-Version V3.0 enthält, ohne Eingriffe übersetzt werden kann. Eine vollständige Kompatibilität zum C++-Compiler V2.2 ist jedoch nicht gewährleistet.
Wenn ein Programm beim Übersetzen mit dem C++-Compiler V2.2 einen Fehler produziert hat, kann es sein, dass der C/C++-Compiler V4.0 im Cfront-C++-Modus einen anderen oder auch keinen Fehler produziert. Im Folgenden werden einige Sprachbesonderheiten beschrieben, die nur für den Cfront-C++-Modus gelten.
const
-Qualifikationen für denthis
-Parameter können in gewissen Kontexten ignoriert werden, z.B.struct A { void f() const; }; void (A::*fp)() = &A::f;
Dies ist tatsächlich eine sichere Operation. Einem Zeiger auf eine Funktion vom Typ
const
kann ein Zeiger auf einen Typ zugewiesen werden, der nichtconst
ist, da es in einem Aufruf, der den Zeiger benutzt, erlaubt ist, das Objekt zu verändern, und die Funktion, auf die gezeigt wird, das Objekt nicht verändert. Eine Zuweisung in die umgekehrte Richtung würde nicht sicher sein.Konversions-Operatoren, die nach
void
konvertieren sind erlaubt.Eine
friend
-Deklaration kann einen neuen Typ einführen. Einefriend
-Deklaration, die einen ausführlichen Typspezifizierer weglässt, ist im C++-Modus erlaubt, aber im Cfront-Modus kann auch ein neuer Typname eingeführt werden.struct A { friend B; };
Der dritte Operator des
?
-Operators ist syntaktisch ein Bedingungsausdruck statt eines Zuweisungsausdrucks.Eine Referenz auf einen Zeigertyp kann von einem Zeigerwert initialisiert werden, ohne dass eine temporäre Variable benutzt werden muss. Dies ist sogar dann möglich, wenn der Referenz-Zeigertyp zusätzliche Typ-Qualifikationen zu denen im Zeigerwert hat.
int *p;const int *&r = p; // No temporary used
Eine Referenz-Variable kann mit 0 initialisiert werden.
Da im Cfront-Modus die Zugreifbarkeit von Typen nicht überprüft wird, werden Typ-Zugriffsfehler als Warnung und nicht als Fehler ausgegeben.
Beim Aufruf von überladenen Funktionen muss ein Nullzeiger als Zeichenkette in der Form "0" geschrieben werden. Andere Schreibweisen, z.B.
const
-Variablen mit dem Wert 0 oder Konstanten in der Form '\0' werden vom Compiler im Falle von überladenen Funktionen nicht als Nullzeiger interpretiert.Wenn eine
operator()()
-Funktion Default-Argument-Ausdrücke hat, wird keine Warnung ausgegeben.Für die Deklaration von Zeigervariablen auf Elementfunktionen wird eine alternative Form unterstützt. Diese wird im folgenden Beispiel verdeutlicht:
struct A { void f(int); static void sf(int); typedef void A::T3(int); // nonstd typedef decl typedef void T2(int); // std typedef }; typedef void A::T(int); // nonstd typedef decl T* pmf = &A::f; // nonstd ptr-to-member decl A::T2* pf = A::sf; // std ptr to static mem decl A::T3* pmf2 = &A::f; // nonstd ptr-to-member decl
In diesem Beispiel bezeichnet
T
einen Routinentyp für eine nicht statische Elementfunktion der KlasseA
, der einint
-Argument übergeben wird und dievoid
zurückliefert. Der Gebrauch solcher Typen ist beschränkt auf nicht standardkonforme Deklarationen von Zeigern auf Elementfunktionen. Die kombinierte Deklaration vonT
undpmf
entspricht einer einzigen standardkonformen Deklaration der folgenden Form:void (A::* pmf)(int) = &A::f;
Eine nicht standardkonforme Deklaration außerhalb einer Klassendeklaration, wie z.B. die Deklaration von
T
, ist normalerweise ungültig und würde einen Fehler erzeugen. Für Deklarationen wieA::T3
innerhalb einer Klassendeklaration, ändert dieses Sprachmerkmal die Bedeutung einer gültigen Deklaration.protected
-Klassenelemente werden nicht überprüft, wenn die Adresse einesprotected
-Elements angegeben wird.class B { protected: int i; }; class D : public B {void mf(); }; void D::mf() { int B::* pmi1 = &B::i; // Error except in Cfront mode int D::* pmi2 = &D::i; // OK }
Beachten Sie, dass die Überprüfung von
protected
-Klassenelementen für andere Operationen - alle außer der Deklaration von Zeigeradressen auf Klassenelemente - im Cfront-Modus standardkonform behandelt wird.Der Destruktor einer abgeleiteten Klasse kann implizit den
private
-Konstruktor einer Basisklasse aufrufen.class A { ~A(); }; class B : public A { ~B(); }; B::~B(){} // Error except in Cfront mode
Wenn es zur Vermeidung von Mehrdeutigkeiten notwendig ist, zu entscheiden, ob etwas eine Parameterdeklaration oder ein Argumentausdruck ist, wird die Zeichenfolge Typname-oder-Schlüsselwort (Identifizierer...) als Argument behandelt.
class A { A(); }; double d; A x(int(d)); A(x2);
Gemäß Standard wird
int(d)
als Parameterdeklaration (mit redundanten Klammern) behandelt; entsprechend istx
eine Funktion. Im Cfront-C++-Modus wirdint(d)
als Argument interpretiert undx
als Variable.Die Deklaration
A(x2);
wird im Cfront-C++-Modus ebenfalls nicht standardkonform interpretiert. Gemäß Standard sollte die Anweisung als Deklaration des benannten Objektesx2
interpretiert werden. Im Cfront-C++-Modus wird sie jedoch alscast
vonx2
in den TypA
interpretiert.Auch die folgende Deklaration wird im Cfront-Modus abweichend vom Standard interpretiert:
int xyz(int());
Gemäß Standard wird hier die Funktion
xyz
deklariert, der als Parameter eine Funktion ohne Argument vom Typint
übergeben wird. Im Cfront-Modus wird diese Anweisung als Deklaration eines Objekts interpretiert, das mit dem Wert 0 initialisiert wird.Bitfelder
Ein benanntes Bitfeld kann die Größe 0 haben. Die Deklaration wird behandelt, als ob kein Name deklariert worden wäre.
Einfache Bitfelder, d.h. Bitfelder, die mit dem Typ
int
deklariert sind, sind immerunsigned
.Der Name für einen Typspezifizierer kann ein
typedef
-Name sein, der synonym mit einem Klassennamen ist.typedef class A T; class T *pa; // No error in Cfront mode
Wenn Datentyp-Spezifizierer (auch
signed
oderunsigned
) verdoppelt werden, wird keine Warnung ausgegeben:short short int i; // No warning in Cfront mode
Nach dem letzten Argument in einer Argumentliste ist ein zusätzliches Komma erlaubt:
f(1,2,);
Der cast eines konstanten Zeigers auf eine Elementfunktion in einen Zeiger auf eine Funktion ist möglich. Es wird nur eine Warnung ausgegeben:
struct A {int f();}; main() { int (*p)(); p = (int (*)())A::f; // OK, with warning }
Argumente von Klassentypen, die bitweises Kopieren erlauben und auch Destruktoren haben, werden als Wert übergeben (wie C-Strukturen) und der Destruktor wird für die „Kopie“ nicht aufgerufen. In den anderen C++-Modi wird das Klassenobjekt in ein temporäres Objekt kopiert, die Adresse des temporären Objekts wird als Argument übergeben und der Destruktor wird für das temporäre Objekt aufgerufen, nachdem der Aufruf zurückgekehrt ist. In der Praxis ist das kein großes Problem, da Klassen, die bitweises Kopieren erlauben, normalerweise keine Destruktoren haben.
Wenn eine
typedef
-Deklaration eine unbenannte Klasse enthält, kann dertypedef
-Name als Klassenname verwendet werden.
typedef struct {int i, j; } S; struct S x; // No error in Cfront mode
Ein
typedef
-Name kann in einem expliziten Destruktoraufruf verwendet werden:struct A { ~A(); }; typedef A B; int main() { A *a; a->~B(); // Permitted in Cfront mode }
Zwei Elementfunktionen können mit denselben Parametertypen deklariert werden, wenn die eine statisch und die andere nicht statisch mit einem Funktionsqualifizierer deklariert wird.
class A { void f(int) const; static void f(int); // no error in Cfront mode };
Zwei Funktionen, die den gleichen Namen und sehr ähnliche Parametertypen haben, können nicht gemeinsam benutzt werden. Dies ist der Fall, wenn sich die Parametertypen nur in den folgenden Aspekten unterscheiden:
char vs. signed char;
f(char); f(signed char);
Array-Grenzen
f(char(*x)[15]); f(char(*x)[18]);
Eine const-Qualifikation eines typedef
typedef char c; f(const c*); f(c*);
Indirekte oder kombinierte Nutzung dieser Aspekte
f(char*,int); f(signed char*,int); typedef char c; g(char,c*); g(signed char,const c*);
Werden doch beide Funktionen definiert, so wird das als Duplikat gewertet. Es wird keine Meldung beim Übersetzen ausgegeben.