Это означает, что указанная переменная не указана ни на что. Я мог бы сгенерировать это так:
SqlConnection connection = null;
connection.Open();
Это вызовет ошибку, потому что, пока я объявил переменную «connection
», она не указала ни на что. Когда я пытаюсь вызвать член «Open
», для его устранения нет ссылки, и он будет вызывать ошибку.
Чтобы избежать этой ошибки:
object == null
. Инструмент Resharper JetBrains определит каждое место в вашем коде, которое имеет возможность ошибки нулевой ссылки, позволяя вам ввести нулевую проверку. Эта ошибка является источником ошибок номер один, IMHO.
Общий подход (как используется во многих библиотеках Boost, например) заключается в том, чтобы помещать помощника в пространство имен, называемое details
, возможно, в отдельном заголовке (включенном в заголовок «public»).
Невозможно предотвратить его видимость и возможность вызова, но это довольно четко указывает, что это часть реализации, а не интерфейс.
Установленный прецедент заключается в том, чтобы помещать такие вещи в специально (то есть последовательно) с именем вложенное пространство имен. Boost использует namespace details
, Loki использует namespace Private
. Очевидно, ничто не может помешать кому-либо использовать содержимое этих пространств имен, но оба названия передают смысл, что их содержимое не предназначено для общего потребления.
Как говорится, альтернативой является превращение func1
и func2
из шаблонов бесплатных функций в статические шаблоны функций-членов какого-либо общего класса; таким образом, helper
может просто быть частным членом указанного класса, невидимым для внешнего мира:
struct funcs {
template<typename T>
static void func1(T const& value) {
// ...
helper(value);
}
template<typename T>
static void func2(T const& value) {
// ...
helper(value);
}
private:
template<typename T>
static void helper(T const& value) {
// ...
}
};
Два варианта с головы:
Я хотел бы (как было сказано ранее) создать класс шаблона, сделать все функции static и вспомогательной функцией приватными. Но кроме того, я также рекомендовал бы сделать конструктор закрытым, как показано ниже:
template <typename T>
class Foo{
public:
static void func1(const T& value);
static void func2(const T& value);
private:
Foo();
static void helper(const T& value);
}
Когда вы создадите конструктор private, компилятор не разрешит экземпляры этого шаблона. Таким образом, приведенный ниже код станет незаконным:
#include "foo.h"
int main(){
int number = 0;
Foo<int>::func1(number); //allowed
Foo<int>::func2(number); //allowed
Foo<int>::helper(number); //not allowed, because it's private
Foo<int> foo_instance; //not allowed, because it's private
}
Так зачем кому-то это хотеть? Потому что наличие разных экземпляров, которые ТОЧНО, то же самое, чего вы, вероятно, никогда не захотите. Когда компилятор сообщает вам, что конструктор некоторого класса является закрытым, вы можете предположить, что наличие разных экземпляров этого файла будет неупорядоченным.
Поскольку пользователь вашего кода должен видеть полное определение функции func1
, его реализация или реализация вспомогательной функции могут быть скрыты.
Но если вы переместите реализацию в еще один файл , пользователю будет только предъявлено объявление шаблона :
//templates.h
template< typename T > void f1( T& );
#include <templates_impl.h> // post-inclusion
И определение:
// templates_impl.h
template< typename T > void f1_helper( T& ) {
}
template< typename T > void f1( T& ) {
// the function body
}