Você pode usar a palavra -chave explícita para evitar a conversão automática dos parâmetros do método?

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

Pergunta

Eu sei que você pode usar a palavra -chave C ++ 'explícita' para construtores de classes para evitar uma conversão automática do tipo. Você pode usar esse mesmo comando para evitar a conversão de parâmetros para um método de classe?

Eu tenho dois membros da classe, um que toma um bool como param, o outro um int. Quando liguei para a função com um int, o compilador converteu o param em um bool e chamou o método errado. Eu sei que eventualmente vou substituir o bool, mas por enquanto não quero quebrar as outras rotinas, pois essa nova rotina é desenvolvida.

Foi útil?

Solução

Não, você não pode usar explícito, mas pode fazer isso:

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);
};

Repita esse padrão para cada método que leva o bool ou unsigned int. Não forneça uma implementação para a versão templatizada do método.

Isso forçará o usuário a sempre chamar explicitamente a versão bool ou não assinado int.

Qualquer tentativa de ligar Method com um tipo que não seja bool ou unsigned int deixará de compilar porque o membro é privado, sujeito às exceções padrão às regras de visibilidade, é claro (amigo, chamadas internas etc.). Se algo que tiver acesso chama o método privado, você receberá um erro de vinculador.

Outras dicas

Não. explicit Impede a conversão automática entre classes específicas, independentemente do contexto. E é claro que você não pode fazer isso para aulas embutidas.

A seguir, é apresentado um invólucro muito básico que pode ser usado para criar um forte typedef:

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
}

Uma boa característica dessa abordagem é que você também pode distinguir entre parâmetros diferentes com o mesmo tipo. Por exemplo, você pode ter o seguinte:

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

void foo (Width width, Height height);

Ficará claro para os clientes de 'Foo' que argumento é qual.

Algo que pode funcionar para você é usar modelos. A seguir mostra a função de modelo foo<>() sendo especializado para bool, unsigned int, e int. o main() A função mostra como as chamadas são resolvidas. Observe que as chamadas que usam uma constante int que não especificam um sufixo de tipo foo<int>(), então você receberá uma chamada de erro foo( 1) Se você não se especializar em int. Se for esse o caso, os chamadores que usam uma constante inteira literal terão que usar o "U" Sufixo para obter a chamada para resolver (esse pode ser o comportamento que você deseja).

Caso contrário, você terá que se especializar em int e use o "U" sufixo ou lançar para um unsigned int antes de passar para o unsigned int Versão (ou talvez afirme que o valor não é negativo, se é isso que você deseja).

#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);
}

O Compiler deu aviso "Ambígue", que será suficiente.

Eu estava fazendo o desenvolvimento do TDD e não percebi que esqueci de implementar a chamada correspondente no objeto simulado.

O BOOL é um int que é limitado a 0 ou 1. Esse é o conceito inteiro de retorno 0;, é logicamente o mesmo que dizer, retornar false; (embora não use isso no código).

Você também pode escrever uma versão int que chama o BOOL One.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top