Können Sie das Schlüsselwort explizit verwenden, um die automatische Konvertierung von Methodenparametern zu verhindern?

Können Sie das Schlüsselwort explizit verwenden, um die automatische Konvertierung von Methodenparametern zu verhindern?

Nein, Sie können nicht explizit verwenden, aber Sie können eine Vorlagenfunktion verwenden, um die falschen Parametertypen abzufangen.

Mit C++11 , können Sie die Vorlagenfunktion als delete deklarieren d. Hier ist ein einfaches Beispiel:

#include <iostream>

struct Thing {
    void Foo(int value) {
        std::cout << "Foo: value" << std::endl;
    }

    template <typename T>
    void Foo(T value) = delete;
};

Dies gibt die folgende Fehlermeldung, wenn Sie versuchen, Thing::Foo aufzurufen mit einem size_t Parameter:

error: use of deleted function
    ‘void Thing::Foo(T) [with T = long unsigned int]’

In vor C++11 code, kann dies stattdessen mit einer undefinierten privaten Funktion erreicht werden.

class ClassThatOnlyTakesBoolsAndUIntsAsArguments
{
public:
  // Assume definitions for these exist elsewhere
  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:
  // You can leave these undefined
  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);
};

Der Nachteil ist, dass der Code und die Fehlermeldung in diesem Fall weniger eindeutig sind, daher sollte die Option C++11 ausgewählt werden, wann immer verfügbar.

Wiederholen Sie dieses Muster für jede Methode, die bool akzeptiert oder unsigned int . Stellen Sie keine Implementierung für die vorlagenbasierte Version der Methode bereit.

Dies zwingt den Benutzer, immer explizit die bool- oder unsigned int-Version aufzurufen.

Jeder Versuch, Method anzurufen mit einem anderen Typ als bool oder unsigned int kann nicht kompiliert werden, da das Mitglied privat ist, natürlich vorbehaltlich der Standardausnahmen von Sichtbarkeitsregeln (Freund, interne Anrufe usw.). Wenn etwas, das Zugriff hat, die private Methode aufruft, erhalten Sie einen Linker-Fehler.


Nr. explicit verhindert die automatische Konvertierung zwischen bestimmten Klassen, unabhängig vom Kontext. Und natürlich können Sie das nicht für eingebaute Klassen tun.


Das Folgende ist ein sehr einfacher Wrapper, der verwendet werden kann, um 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
}

Eine nette Eigenschaft dieses Ansatzes ist, dass Sie auch zwischen verschiedenen Parametern mit demselben Typ unterscheiden können. Sie könnten zum Beispiel Folgendes haben:

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

void foo (Width width, Height height);

Den Kunden von 'foo' wird klar sein, welches Argument welches ist.