Можно ли использовать ключевое слово, явное для предотвращения автоматического преобразования параметров метода?

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null.

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

51
задан Jeffrey Bosboom 23 April 2017 в 08:00
поделиться

8 ответов

Нет, Вы не можете использовать явный, но можно сделать это вместо этого:

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

Повторение этот шаблон для каждого метода, который берет bool или unsigned int. Не обеспечивайте реализацию для templatized версии метода.

Это будет вынуждать пользователя к всегда явно вызову bool или неподписанная международная версия.

Любая попытка звонить Method с типом кроме bool или unsigned int не скомпилирует, потому что участник является частным согласно стандартным исключениям к правилам видимости, конечно (друг, внутренние вызовы, и т.д.). Если что-то, что действительно имеет доступ, назовет закрытый метод, Вы получите ошибку компоновщика.

66
ответ дан Apollys supports Monica 7 November 2019 в 10:11
поделиться

Нет. explicit предотвращает автоматическое преобразование между определенными классами, независимо от контекста. И конечно Вы не можете сделать этого для встроенных классов.

14
ответ дан Lev 7 November 2019 в 10:11
поделиться

Следующее является очень простой оберткой, которая может использоваться для создания сильного определения типа:

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
}

Одна хорошая функция этого подхода, то, что можно также различать различные параметры с тем же типом. Например, у Вас могло быть следующее:

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

void foo (Width width, Height height);

Это будет ясно клиентам 'нечто', которое аргумент который.

7
ответ дан Community 7 November 2019 в 10:11
поделиться

Что-то, что могло бы работать на Вас, должно использовать шаблоны. Следующие шоу шаблонная функция foo<>() специализируемый для bool, unsigned int, и int. main() функция показывает, как вызовы разрешены. Обратите внимание, что вызовы, которые используют константу int, которые не определяют суффикс типа, решат к foo<int>(), таким образом, Вы получите ошибку при вызове foo( 1), если Вы не специализируетесь на int. Если это верно, вызывающие стороны, использующие литеральную целочисленную константу, должны будут использовать эти "U" суффикс, чтобы заставить вызов решать (это могло бы быть поведением, которое Вы хотите).

Иначе необходимо будет специализироваться на [1 111] и использовать эти "U" суффикс или бросить его к unsigned int перед передачей его к unsigned int версия (или возможно сделать утверждение, что значение не отрицательно, если это - то, что Вы хотите).

#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);
}
2
ответ дан Michael Burr 7 November 2019 в 10:11
поделиться

Компилятор дал "неоднозначный вызов" предупреждение, которое будет достаточно.

я делал разработку TDD и не понял, что забыл реализовывать соответствующий вызов в фиктивном объекте.

0
ответ дан Superpolock 7 November 2019 в 10:11
поделиться

bool ЯВЛЯЕТСЯ интервалом, который ограничен или 0 или 1. Это - целое понятие возврата 0; это - логически то же, что возвращают false; (не используйте это в коде хотя).

0
ответ дан WolfmanDragon 7 November 2019 в 10:11
поделиться

Вы могли также записать международную версию, которая называет bool один.

-1
ответ дан aib 7 November 2019 в 10:11
поделиться

В настоящее время принимаемый ответ (использование частной шаблонной функции) хорош, но устарел. С C++ 11, мы можем использовать delete функции d вместо этого:

#include <iostream>

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

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

int main() {
    Thing t;
    int int_value = 1;
    size_t size_t_value = 2;

    t.Foo(int_value);

    // t.Foo(size_t_value);  // fails with below error
    // error: use of deleted function
    //   ‘void Thing::Foo(T) [with T = long unsigned int]’

    return 0;
}

Это передает намерение исходного кода более непосредственно и предоставляет пользователя более четкое сообщение об ошибке при попытке использовать функцию с запрещенными типами параметра.

1
ответ дан 7 November 2019 в 10:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: