Проверьте, имеет ли класс функцию членства данной подписи

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

124
задан Stephen Kennedy 11 November 2018 в 12:24
поделиться

4 ответа

Я не уверен, понимаю ли я Вас правильно, но можно использовать SFINAE для обнаружения функционального присутствия во время компиляции. Пример из моего кода (тестирует, если класс имеет функцию членства size_t used_memory () константа).

template<typename T>
struct HasUsedMemoryMethod
{
    template<typename U, size_t (U::*)() const> struct SFINAE {};
    template<typename U> static char Test(SFINAE<U, &U::used_memory>*);
    template<typename U> static int Test(...);
    static const bool Has = sizeof(Test<T>(0)) == sizeof(char);
};

template<typename TMap>
void ReportMemUsage(const TMap& m, std::true_type)
{
        // We may call used_memory() on m here.
}
template<typename TMap>
void ReportMemUsage(const TMap&, std::false_type)
{
}
template<typename TMap>
void ReportMemUsage(const TMap& m)
{
    ReportMemUsage(m, 
        std::integral_constant<bool, HasUsedMemoryMethod<TMap>::Has>());
}
88
ответ дан 24 November 2019 в 01:05
поделиться

Хорошо. Вторая попытка. Это хорошо, если Вам не нравится этот также, я ищу больше идей.

статья Herb Sutter говорит о чертах. Таким образом, у Вас может быть класс черт, чье инстанцирование по умолчанию имеет поведение нейтрализации, и для каждого класса, где Ваша функция членства существует, затем класс черт специализирован для вызова функции членства. Я полагаю, что статья Herb упоминает технику, чтобы сделать это так, чтобы она не включала большое копирование и вставку.

Как я сказал, тем не менее, возможно, что Вы не хотите дополнительную работу, связанную с "метками" классов, которые действительно реализуют того участника. В этом случае я смотрю на третье решение....

2
ответ дан 24 November 2019 в 01:05
поделиться

Чтобы быть ненавязчивыми, можно также поместить serialize в пространство имен класса, сериализируемого, или класса архива, благодаря поиск Koenig . См. Пространства имен для бесплатных Функциональных Переопределений для получения дополнительной информации. :-)

Открытие любого данного пространства имен для реализации бесплатной функции является Просто Неправильным. (например, Вы, как предполагается, не открываете пространство имен std для реализации swap для собственных типов, но должны использовать поиск Koenig вместо этого.)

3
ответ дан 24 November 2019 в 01:05
поделиться

Это должно быть достаточно, если Вы будете знать название функции членства, то Вы ожидаете. (В этом случае функции bla не удается инстанцировать, если нет никакой функции членства (пишущий тот, который работает, так или иначе жестко, потому что существует отсутствие функциональной частичной специализации. Вы, возможно, должны использовать шаблоны классов) кроме того, разрешать структура (который подобен enable_if), мог также быть шаблонным на типе функции, которую Вы хотите, чтобы это имело как участник.

template <typename T, int (T::*) ()> struct enable { typedef T type; };
template <typename T> typename enable<T, &T::i>::type bla (T&);
struct A { void i(); };
struct B { int i(); };
int main()
{
  A a;
  B b;
  bla(b);
  bla(a);
}
12
ответ дан 24 November 2019 в 01:05
поделиться
Другие вопросы по тегам:

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