2016-12-28 4 views
2

Я всегда читал, что частный конструктор предотвращает создание объекта. Я использовал их в одиночных шаблонах, и я знаю, как создавать объекты при использовании частного конструктора (используя статические методы и т. Д.). Я знаю, что конструкторы используются для инициализации объектов.почему частный конструктор предотвращает создание объекта C++

Но я не понимаю, что именно делает частные конструкторы препятствием для создания объекта. Что делать, если мой объект не инициализируется. Я имею в виду, что он должен бросить мусор, но почему он ограничивает?

Я проверил все существующие ответы в stackoverflow, но я не получаю точной концепции.

ответ

3

Чтобы создать объект в C++, конструктор должен называться. Если конструктор, который нужно вызвать, недоступен, его нельзя вызвать, и объект не может быть создан.

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

Если конструктор не может быть вызван, объект не может быть инициализирован. В конце концов, задача конструктора - инициализировать объект. Но если конструктор недоступен, то объект не может быть построен, поэтому невозможно иметь неинициализированный объект.

Конечно, нет ничего препятствующего тому, чтобы класс имел несколько конструкторов с различными элементами управления доступом (private, protected и public). A class с конструктором public может быть построен с использованием этого конструктора любым кодом. Но любая попытка использовать конструктор private (не-членом не friend) по-прежнему будет отклонена. Таким образом, управление доступом позволяет (разработчику) class определенную степень контроля над тем, как создается экземпляр.

Не определяющий (т. Е. Не реализующий) конструктор предотвращает конструкцию объекта. Если этот конструктор равен private, компилятор отклонит попытку вызвать его (если только функция, пытающаяся создать экземпляр, не является членом или friend, как указано выше). Для участников и друзей класса компилятор разрешает доступ к конструктору, но (в типичной компиляции компиляции-потом-ссылки) компоновщик не будет создавать исполняемый файл, поскольку он не может разрешить вызов функции, которая не определена , Используя технику маркировки конструктора private и не определяя его, он является распространенным способом предотвращения создания кода экземпляром класса (путем предотвращения компиляции кода или предотвращения его запуска).

+0

Итак, я понимаю, что отношение между объектом и конструктором заключается в том, что 1) я создаю объект «ClassName obj» 2) это объявление вызывает конструктор классов «ClassName()» 3) этот конструктор выделяет память. и это завершает процесс создания объекта. Если мой объект не может вызвать конструктор, память не будет выделена, и объект не будет создан. Правильно ли я понимаю? - –

+0

Не совсем. Создание объекта с использованием класса ClassName obj; 'вызывает конструктор, который не может принимать никаких аргументов, - который может быть конструктором без фактических аргументов (' ClassName :: ClassName() ') или конструктором со всеми аргументами, имеющими значения по умолчанию (например, объявленные в определение класса как 'ClassName (int x = 0)'). Память для объекта (экземпляр «ClassName») выделяется перед вызовом конструктора, а затем инициализируется конструктором (слабо превращается в объект). Если конструктор недоступен, компилятор не разрешает создание объекта, поэтому код не будет компилироваться. – Peter

2

C++ не позволяет создавать объекты без вызова конструктора. И если конструктор недоступен, создание не может быть выполнено. Время жизни объекта: определено между вызовами конструктора и деструктора.

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

0

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

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

+0

Так из всех приведенных выше замечаний, я понимаю, что отношение между объектом и конструктором является то, что 1) создать объект «ИмяКласс OBJ» 2) это заявление вызывает конструктор класса «ИмяКласс()» 3) этот конструктор выделяет память , и это завершает процесс создания объекта. В случае, если объект не может вызвать конструктор, память не будет выделена, и объект не будет создан. Я правильно понял? –

4

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

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

3

класс private scope не предотвращает создание экземпляра класса, но на самом деле он ограничивает «кто» может создать объект.

это, как и другие данные членов в частном порядке контекстными, которые не могут быть доступны снаружи, но только для accessors и getters и других `другу функций и классов:

#include <iostream> 
using namespace std; 

class Foo 
{ 
    public: 
     Foo(int x) : value(x){ cout << "Foo(int) public ctor" << endl;} // ctor 

     void SetValue(int x) {value = x;} // setter 
     int GetValue()const{return value;}// getter 

    private: 
     int value; 
     Foo(){ cout << "Foo() private ctor" << endl;} // private ctor 

     friend ostream& operator<<(ostream& out, Foo& rhs) 
     { 
      out << rhs.value; 
      return out; 
     } 
     friend Foo* CreateObject(); 
}; 

Foo* CreateObject() 
{ 
    Foo* ptrFoo = new Foo; 
    return ptrFoo; 
} 


int main() 
{ 

    //Foo theFoo;  // error C2248: 'Foo::Foo' : cannot access private member declared in class 'Foo' 
    Foo theFoo2(0); // ok 
// cout << theFoo2.value << endl; // error C2248: 'value' : cannot access private member declared in class 'Foo' 
    cout << theFoo2.GetValue() << endl; // ok 
    cout << theFoo2 << endl; 

    Foo* ptrFoo = CreateObject(); 
    ptrFoo->SetValue(7); 
    cout << ptrFoo->GetValue() << endl; 


    cout << endl; 
    return 0; 
}