Frage

Ich schreibe ein Programm unter MS Visual C ++ 6.0 (ja, ich weiß, es ist alten, nein es gibt nichts, was ich tun kann, um ein Upgrade). Ich sehe einige Verhalten, das ich denke, wirklich seltsam ist. Ich habe eine Klasse mit zwei Konstrukteuren wie folgt definiert:

class MyClass
{
public:
    explicit MyClass(bool bAbsolute = true, bool bLocation = false) : m_bAbsolute(bAbsolute), m_bLocation(bLocation) { ; }
    MyClass(const RWCString& strPath, bool bLocation = false);

private:
    bool m_bAbsolute;
    bool m_bLocation;
};

Wenn ich eine Instanz dieser Klasse mit dieser Syntax instanziiert: MyClass("blah"), ruft er den ersten Konstruktor. Wie Sie sehen können, habe ich das explicit Schlüsselwort in der Hoffnung darauf, dass es das nicht tun würde ... keine Würfel. Es scheint, die Umwandlung von const char * zu bevorzugen über die Umstellung auf bool RWCString, die eine Kopie Konstruktor hat, der eine const char * nimmt. Warum es das tun? Ich würde das bei zwei möglichen Entscheidungen wie diese annimmt, würde es sagen, es ist nicht eindeutig. Was kann ich es dies zu tun, um zu verhindern tun? Wenn möglich, würde Ich mag ausdrücklich zu vermeiden, um das strPath Argument zu einem RWCString zu werfen, wie es mit Literalen viel verwendet werden wird, und das ist eine Menge zusätzlicher Eingabe (plus ein wirklich einfacher Fehler zu machen).

War es hilfreich?

Lösung

Explicit wird hier nicht helfen, da der Konstruktor nicht Teil der impliziten Umwandlung ist, nur der Empfänger.

Es gibt keinen Weg, um die bevorzugte Reihenfolge der Conversions zu steuern, aber man konnte einen zweiten Konstruktor hinzufügen, die eine char nahm *. Z. B:

class MyClass
{
public:
    MyClass(bool bAbsolute = true, bool bLocation = false);
    MyClass(const RWCString& strPath, bool bLocation = false);
    MyClass(const char* strPath, bool bLocation = false);

private:
    bool m_bAbsolute;
    bool m_bLocation;
};

Andere Tipps

Andrew Grant-brachte die Lösung. Ich möchte Sie sagen, warum es nicht so, wie Sie versucht haben, nicht funktioniert. Wenn Sie zwei lebensfähige Funktionen für ein Argument haben, dann derjenige, der das Argument am besten entspricht aufgerufen. Die zweite erfordert eine benutzerdefinierte Umwandlung, während die erste braucht nur eine Standardkonvertierung. Deshalb ist der Compiler die erste über die zweite vorzieht.

Wenn Sie don t es behalten wollen Gießen, dann scheint es mir, dass Sie einen anderen Ctor zu machen haben könnte, die ein const char nimmt *

.

Das ist, was ich wohl in dieser Situation tun würde.

(nicht sicher, warum Sie eine Ctor mit einer Art machen, dass Sie nicht für die meisten seiner Verwendung sind vorbei.)

edit:

Ich sehe schon jemand anderes diese während ich geschrieben tippte Mine

Nicht sicher, warum es einen Verweis auf eine Zeichenfolge und ein Bool verwechseln sollte? Ich habe Probleme mit einem Bool und ein int gesehen.
Können Sie den Standardwert für den ersten Konstruktor verlieren - es da dies sein kann, dass es das Standard-Konstruktor für MyClass macht (), dann ist es auch der Standard, wenn es nicht die args mithalten kann

Sie haben die Wahl einen Konstruktor hinzuzufügen, die explizit einen const char * nimmt

MyClass(const char* strPath, bool bLocation = false); // Thanks Andrew Grant!

Oder

MyClass( string("blah") );

Der Compiler intrinsisch weiß, wie ein const char zu machen * in einen bool. Es wäre die Suche zu gehen, um zu sehen, wenn für eine der ersten Argumenttypen von MyClass Bauer, gibt es einen Konstruktor, der den Quelltyp nehmen Sie ihnen gegeben haben, oder wenn sie es auf eine Art werfen können, die von akzeptiert einer des Konstrukteure von einem der ersten Argumenttypen Ihres MyClass Bauer, oder ... na ja, sehen Sie, wohin dies geht und das ist nur für das erste Argument. Auf diese Weise liegt Wahnsinn.

Das explicit Schlüsselwort teilt den Compiler implizit einen Wert des Typs Argument in ein Objekt der Klasse nicht konvertieren kann, wie in

struct C { explicit C( int i ): m_i(i) {}; int m_i; };
C c = 10;//disallowed
C c( 2.5 ); // allowed

C ++ hat eine Reihe von Regeln, welcher Konstruktor zu bestimmen, ist in Ihrem Fall genannt werden -. Ich weiß nicht, von der Rückseite von meinem Kopf, aber Sie können intuitiv erkennen, dass die Standardargumente gegen Zweideutigkeit führen

Sie müssen sich durch diese Vorgaben denken.

Sie können den Rückfall auf einig statischen, mit dem Namen, Bauweisen. Oder können Sie eine andere Klasse verwenden (die von einer Design-Sicht keine schlechte Wahl ist). So oder so, können Sie den Client-Code entscheiden, welches Konstruktor zu verwenden.

struct C {
  static C fromString( const char* s, const bool b = true );
  static C fromBools( const bool abs = true, const bool b = true );
};

oder

struct CBase {
    bool absolute; 
    bool location;
    CBase( bool abs=true, bool loc=true );
};

struct CBaseFromPath {
    // makes 'absolute' true if path is absolute
    CBaseFromPath( const char* s, const bool loc );
};

Sind Sie sicher , dass es wirklich die erste Konstruktor ruft? Sind Sie es mit der Zeichenfolge hartcodierte Aufruf, oder ist es hinter einem #define versteckt? Sind Sie sicher, dass die #define ist das, was Sie denken, es ist? (Versuchen Sie, mit der / Ef Option die Erstellung der erweiterten Präprozessorausgabe zu erhalten, und sehen, ob der Anruf aussieht wie man erwarten würde es aussehen.)

EDIT: Auf der Grundlage dieser und anderer Kommentare, ist mein Vorschlag anderen Konstruktor hinzufügen für const char*. Ist das machbar

?
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top