2009-07-13 10 views
2

Ich habe einen Konvertierungsoperator, der einen const Zeiger zurückgibt, und ich muss ihn const_cast. Das funktioniert jedoch zumindest unter MSVC8 nicht. Der folgende Code gibt mein Problem wieder:Warum kann ich die Rückgabe des Konvertierungsoperators nicht const_cast?

class MyClass { 
public: 
    operator const int*() { 
     return 0; 
    } 
}; 

int main() { 
    MyClass obj; 
    int* myPtr; 
    // compiles 
    const int* myConstPtr = obj; 
    // compiles 
    myPtr = const_cast<int*>(myConstPtr); 
    // doesn't compile (C2440: 'const_cast' : cannot convert from 'MyClass' to 'int *') 
    myPtr = const_cast<int*>(obj); 
} 

Warum ist das? Es scheint kontraintuitiv zu sein. Vielen Dank!

+1

Versuchen Sie wirklich, einen Nullzeiger mit 'const int *' zurückzugeben?Es ist in der Regel auch eine schlechte Übung, eine Klasse stillschweigend in einen Zeiger auf ein Primitiv umwandeln zu können. (Zum Beispiel kann 'std :: string' nicht in' const char * 'umgewandelt werden, sondern stellt stattdessen eine Methode' .c_str() 'zur Verfügung, die einen Zeiger auf ihre Daten zurückgibt. Dies ist viel sicherer, weil der Programmierer sehr stark sein muss bewusst, was er tut.) –

+0

@Seth: Danke. Das ist nicht mein wirklicher Code; es ist nur etwas, was ich geschrieben habe, um den Fehler zu reproduzieren, den ich bekomme! Seien Sie versichert, ich gebe keine Null-Zeiger absichtlich zurück :-) In meinem Fall ist die Klasse ein dünner Wrapper um ein Byte-Array, und ich möchte, dass ihre Clients es verwenden, als wäre es eins. –

+0

Wenn Sie beabsichtigen, dass Benutzer das Bytearray direkt bearbeiten können, sollten Sie ihnen einen nichtkonstanten Operator int *() 'geben. Im Allgemeinen geben Sie nur die const-Version impliziert, dass Sie Lesevorgänge zulassen, aber nicht ändern. Die Benutzer zu zwingen, eine 'const_cast' zu machen, ist ein Fehler in meinem Buch. –

Antwort

4

Um es Sie arbeiten zu tun haben:

myPtr = const_cast<int*>(static_cast<const int*>(obj)); 

Wenn Sie direkt const_cast, der Compiler Look für den Cast-Operator in int *.

1

Sie können const_cast nur verwenden, um in einen nicht konstanten Zeiger des gleichen Typs zu konvertieren (um Konstanz wegzuwerfen). Um zwischen nicht verwandten Typen zu konvertieren, müssen Sie reinterpret_cast verwenden.

+0

Danke! Ich dachte nur, der Compiler würde herausfinden, 'MyClass' kann automatisch in' int * 'konvertiert werden, wie in" const int * myConstPtr = obj' " –

+1

Nein, nein, nein! Er hat den Umwandlungsoperator von MyClass nach int * erstellt, damit die Typen * verwandt sind. static_cast ist geeignet. reinterpret_cast ruft den Operator nicht auf. Glücklicherweise wird es nicht kompiliert, da obj kein Zeiger ist und reinterpret_cast entweder einen Zeiger oder einen Integer-Typ benötigt und obj keins ist. –

-1

Wahrscheinlich wäre es klarer zu Ihrem Compiler, wenn Sie etwas tun:

myPtr = const_cast<int*>(obj()); 

Ich habe noch nicht versucht, dachte.

EDIT: Sollte der Bediener Erklärung nicht so etwas wie:

const int* operator() { 
+0

Funktioniert nicht: C2064: Begriff wird nicht zu einer Funktion ausgewertet, die 0 Argumente enthält. –

+0

Ich habe immer verwendet: const int * operator()() {...} - nicht sicher, wo die Funktionsdefinition des OP kam, aber anscheinend kompiliert. –

+0

Die OP-Definition ist von einem Konvertierungsoperator zu const int *. Samirs Definition ist der "Funktionsaufruf" -Operator(), der keine Parameter annimmt und const int * zurückgibt. Obwohl die beiden Operatoren dieselben Ein- und Ausgaben haben, werden sie vom Compiler in verschiedenen Situationen verwendet. –

1

Denken Sie an const_cast<> als Funktion Vorlage

template <typename Target, typename Source> 
Target const_cast(Source src); 

(das ist nicht, wie es umgesetzt, aber es hilft hier stell dir vor es war). Dann wird Source als MyClass abgeleitet, und es gibt nichts const_cast kann tun, um ein int * von einer MyClass zu erhalten.

Was Sie wollen, ist eine der folgenden:

const_cast<int*>(static_cast<const int*>(obj) /* invokes operator const int* */); 
// or 
const_cast<int*>(obj.operator const int*()); 
+0

Ja, 'myPtr = const_cast (obj.operator const int *());' funktioniert! Das ist ein hässlicher Code. –

1

const_cast kann nur die Konstanz eines Typs ändern. Wenn Sie den impliziten Operator aufrufen möchten, benötigen Sie eine static_cast und dann eine const_cast. Während es nervig ist, stellt es sicher, dass Sie explizit in dem sind, was Sie tun.

myPtr = const_cast<int*>(static_cast<const int*>(obj)); 

Sie können auch die alte Schule c-Casts Operator

myPtr = (int*)(const int*)obj; 

Aber das ist sehr aus mehreren Gründen abgeraten verwenden:

  • Es ist grepable nicht
  • Sie kann sehr leicht mehr tun, als Sie beabsichtigt haben. Meistens wollen Sie nicht mit const_cast Operationen arbeiten und das static_cast erzwingt dies. In der Tat wollen Sie sehr selten eine const_cast. Wenn Sie es regelmäßig tun, haben Sie einige Designfehler.

Edit: Ich war etwas abseits, ich habe es jetzt behoben. Es macht die C-Stil-Besetzung ein wenig hässlicher

+1

Der C-Style-Cast wird auch in diesem Fall aus dem Grund abgeraten, weil er nicht kompiliert - er versucht, eine Instanz von MyClass zu werfen, kein Zeiger. –

+0

lol, hoppla, ich habe es jetzt behoben. –