Können Sie Schlüsselwort explizit zu verhindern automatische Konvertierung von Methodenparameter verwenden?

StackOverflow https://stackoverflow.com/questions/175689

Frage

Ich weiß, Sie C ++ Schlüsselwort verwenden können ‚explizite‘ für den Bau von Klassen eine automatische Konvertierung von Typ zu verhindern. Können Sie diesen gleichen Befehl verwenden, um die Umwandlung von Parametern für eine Klassenmethode zu verhindern?

Ich habe zwei Klassenmitglieder, eine, die einen bool als param nimmt, der andere ein unsigned int. Wenn ich die Funktion mit einem int genannt, konvertiert der Compiler die param zu einem bool und die falsche Methode genannt. Ich weiß, schließlich werde ich den Bool ersetzen, aber jetzt wollen nicht, die anderen Routinen zu brechen, wie diese neue Routine entwickelt wird.

War es hilfreich?

Lösung

Nein, können Sie nicht explizit verwenden, aber Sie können dies tun, statt:

class ClassThatOnlyTakesBoolsAndUIntsAsArguments
{
public:
  void Method(bool arg1);
  void Method(unsigned int arg1);

  // Below just an example showing how to do the same thing with more arguments
  void MethodWithMoreParms(bool arg1, SomeType& arg2);
  void MethodWithMoreParms(unsigned int arg1, SomeType& arg2);

private:
  template<typename T>
  void Method(T arg1);

  // Below just an example showing how to do the same thing with more arguments
  template<typename T>
  void MethodWithMoreParms(T arg1, SomeType& arg2);
};

Wiederholen Sie diese Muster für jede Methode, die die bool oder unsigned int nimmt. Sie nicht eine Implementierung für die templatized Version des Verfahrens zur Verfügung stellen.

Dies wird den Benutzer zwingen, immer explizit die Bool oder unsigned int Version aufrufen.

Jeder Versuch Method mit einem anderen Typ als bool oder unsigned int anrufen wird nicht kompilieren, da das Mitglied der Standard Ausnahmen Sichtbarkeitsregeln, natürlich (Freund, interner Anrufe, etc.) privat, unterliegt. Wenn etwas, das Zugriff hat die private Methode aufruft, erhalten Sie einen Linker-Fehler erhalten.

Andere Tipps

Nein. explicit verhindert automatische Konvertierung zwischen spezifischen Klassen, und zwar unabhängig von Kontext. Und natürlich können Sie nicht tun es für integrierte Klassen.

Das folgende ist ein sehr einfaches Wrapper, der verwendet werden kann, eine starke typedef zu erstellen:

template <typename V, class D> 
class StrongType
{
public:
  inline explicit StrongType(V const &v)
  : m_v(v)
  {}

  inline operator V () const
  {
    return m_v;
  }

private:
  V m_v; // use V as "inner" type
};

class Tag1;
typedef StrongType<int, Tag1> Tag1Type;


void b1 (Tag1Type);

void b2 (int i)
{
  b1 (Tag1Type (i));
  b1 (i);                // Error
}

Ein nettes Feature dieses Ansatzes ist, dass Sie auch zwischen verschiedenen Parametern mit dem gleichen Typ unterscheiden können. Zum Beispiel könnten Sie folgende Voraussetzungen erfüllt sein:

class WidthTag;
typedef StrongType<int, WidthTag> Width;  
class HeightTag;
typedef StrongType<int, HeightTag> Height;  

void foo (Width width, Height height);

Es wird für die Kunden von ‚foo‘ klar sein, das Argument ist, welche.

Etwas, das für Sie arbeiten ist Vorlagen. Im Folgenden wird die Template-Funktion foo<>() für bool, unsigned int spezialisiert ist und int. Die main() Funktion zeigt, wie die Anrufe gelöst bekommen. Beachten Sie, dass die Anrufe, die eine konstante int verwenden, die foo<int>() keinen Typ Suffix angeben wird lösen zu, so dass Sie einen Fehler Aufruf foo( 1), wenn man auf int nicht spezialisiert. Wenn dies der Fall ist, können Anrufer ein wörtliches Integer-Konstante verwendet haben die "U" Suffix verwenden, um den Anruf zu bekommen zu lösen (dies könnte das Verhalten, das Sie wollen sein).

Ansonsten werden Sie auf int spezialisiert haben und die "U" Suffix verwenden oder auf ein unsigned int zu werfen, bevor es auf die unsigned int Version vorbei (oder vielleicht tun einen behaupten, dass der Wert nicht negativ ist, wenn es das ist, was Sie wollen ).

#include <stdio.h>

template <typename T>
void foo( T);

template <>
void foo<bool>( bool x)
{
    printf( "foo( bool)\n");
}


template <>
void foo<unsigned int>( unsigned int x)
{
    printf( "foo( unsigned int)\n");
}


template <>
void foo<int>( int x)
{
    printf( "foo( int)\n");
}



int main () 
{
    foo( true);
    foo( false);
    foo( static_cast<unsigned int>( 0));
    foo( 0U);
    foo( 1U);
    foo( 2U);
    foo( 0);
    foo( 1);
    foo( 2);
}

Compiler gab „mehrdeutig Aufruf“ Warnung, die ausreichend.

Ich war TDD Entwicklung zu tun und wusste nicht, dass ich den entsprechenden Aufruf in dem Mock-Objekt zu implementieren vergessen.

Bool ist ein int, die entweder 0 oder 1 beschränkt ist, dass das gesamte Konzept der Rückkehr ist 0 ;, es ist logisch die gleichen wie zu sagen return false; (nicht zu, obwohl im Code verwenden).

Sie können auch eine int-Version schreiben, die die Bool nennt.

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