2013-06-26 3 views
3

Предположим, что у нас есть одноэлементный класс, где функция экземпляра (функция, возвращающая экземпляр singleton класса) была перегружена. Одна версия принимает некоторые параметры и инициализирует объект в конструкторе класса, другая версия не принимает никаких параметров.Как заставить стиль использования для одноэлементного класса

1. myClass::Instance (int x, int y); 
2. myClass::Instance (); 

Чего мы хотим добиться того, что пользователь класса должен всегда вызывать (1) первый и все последующие вызовы должны быть сделаны только в (2). Пользователю не разрешается совершать первый вызов (2), и после того, как вызов (1) не будет выполнен, последующие вызовы (1) не будут разрешены.

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

+3

Очевидно, что первый вопрос должен быть, можете ли вы обойтись без Singleton? –

+0

Одиночный класс * исключительно * гарантирует, что экземпляр доступен по запросу. У вас нет (да, он доступен, но вы должны сначала вызвать эту функцию). Если ответственность за создание экземпляра связана с пользователем, то у вас совсем нет сингла (что может быть или не быть плохим). –

+0

@Matthieu M. К сожалению, Синглтон необходим в ситуации. – StudentX

ответ

2

В 1. Если экземпляр уже существует, вы выбрали исключение (например, std :: logic_error). Если нет, вы создаете экземпляр с предоставленными параметрами и возвращаете его.

В 2. Если экземпляр еще не существует, вы генерируете исключение (например, std :: logic_error). Затем вы возвращаете его.

3

Проблема заключается в том, что компилятор не может компилировать это понятие «первого вызова» во время компиляции (поскольку он компилирует определенную единицу перевода, он не знает, можно ли (1) вызывать из некоторого другой блок перевода), так что вы должны:

  • дизайн, чтобы ограничить доступ к одной или оба перегрузкам во время компиляции, и/или
  • проверки действительного использования во время выполнения, и/или
  • сделать свой более терпимым к нескольким вызовам (1), гарантируя, что вы получите нужное поведение.

Есть много возможных подходов, которые могут или не могут хватить:

  • вы могли бы (1) труднее получить доступ, сделав его защитой, или частное при предоставлении дружбы к конкретному коду, который будет вызывать она, в результате чего (2) общественности для удобного постоянного использования другими частями кода

  • вы могли бы написать код (1) так, что после того, как в первый раз она игнорирует все аргументы и вызывает (2)

  • вы могли бы утверждения подтверждения использования во время выполнения, который мы надеемся обеспечить клиентский код соответствует вашим условиям задолго до того, он попадает в производство

  • вы могли бы (1) вернуть то, что нужно для вызова (2) , такой как объект типа, который не может быть создан клиентом, но это не мешает (1) снова быть вызванным. Этот необходимый объект может быть передан конструктору (2), или (2) может стать функцией этого объекта.

+0

+1 для «дизайна для ограничения доступа к одной или обеим перегрузкам во время компиляции». – MattDavey

0

Для этого можно использовать std :: call_once (http://en.cppreference.com/w/cpp/thread/call_once). Вам понадобится отдельный участник (http://en.cppreference.com/w/cpp/thread/once_flag) (скажем m_once_flag).

В 1: Вы завершаете свою реализацию вокруг call_once с m_once_flag как первый параметр.

В 2: Вы называете 1.

call_once позаботится о том, что функция выполняется только в первый раз вокруг.