4

Например это правильно:Правильно ли использовать объявление только для пустых частных конструкторов в C++?

class C 
{ 
    private: 
    C(); 
    C(const & C other); 
} 

или вы скорее должны обеспечить определение (ы):

class C 
{ 
    private: 
    C() {}; 
    C(const & C other) {}; 
} 

? Спасибо за текущие ответы. Давайте продолжим этот вопрос: компилятор генерирует более эффективный код в одном из этих примеров? Я могу представить, что предоставление тела для компилятора ctor force включает некоторый (пустой) код в блок компиляции? Это также верно для автоматически сгенерированного кода?

+1

Чтобы сказать, какой из них «правильный», нам нужно знать, какова ваша цель. – sellibitze

ответ

10

Если вы не хотите, чтобы ваш объект был доступен для копирования, тогда нет необходимости предоставлять реализацию. Просто объявите копию ctor конфиденциальной без какой-либо реализации. То же самое относится и к другим ctors, если вы не хотите, чтобы какой-либо из них использовал их, просто объявляйте их частными без какой-либо реализации.

0

Если вы используете декларацию 'empty', компилятор больше не будет генерировать реализацию по умолчанию, и вы получите ошибки связи. Если вы их объявите, вы должны написать их так, чтобы форма пустой скобки была необходима.

+5

Это неправда, вы не получите ошибок ссылок, если вы не называете эти конструкторы. – Paul

+0

Ах. правильно, если существуют другие конструкторы. В коде OP не было. –

0

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

+0

Обратите внимание, что эти конструкторы являются частными и предполагают, что они не будут использоваться самим классом. – doc

+0

Я считаю, что это особенность. Если я не хочу, чтобы кто-либо делал копию - либо клиентов моего класса, либо даже самого себя - тогда я хочу, чтобы компилятор мне сказал, когда я пытаюсь это сделать. –

+1

Игнорируйте меня, я не понял, что они были частными ... :) –

0

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

5

Для запрета данных конструкций, таких как стандартная конструкция или копирование, вы можете использовать конструкторы с объявлениями.

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

О вашей последней редакции: Я ожидаю, что достойный компилятор создаст тот же код для конструктора по умолчанию и для пустого конструктора и без списка инициализации, в конце концов, что ему нужно сделать, это по умолчанию инициализировать каждый член.

+0

Вы имеете в виду ошибки компилятора, а не ошибки компоновщика. – doc

+0

Я имею в виду ошибки компоновщика, все ваши объекты будут компилироваться, и когда они попытаются связать, они обнаруживают, что символ конструктора (const & obj) отсутствует, поэтому ошибка компоновщика. –

+0

Когда конструктор объявляется закрытым, он не будет компилироваться, если вы не используете singleton. – doc

2

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

Иногда полезно предоставить декларацию, но не реализовать конструктор, который вы не хотите использовать. Это часто делается с помощью конструктора копирования для объектов (например, одиночных), которые вы не хотите, чтобы их копии были когда-либо. В таких случаях декларация часто делается частной.

9

Это нормально, если вы их не используете.

С стандартом 0x вы можете использовать deleted functions.

class X { 
    // ... 
    X& operator=(const X&) = delete; // Disallow copying 
    X(const X&) = delete; 
}; 
+0

Спасибо, я тоже хотел бы принять ваш ответ, но это невозможно, и Навин был первым. – doc

2

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

Однако ошибкой компилятора было бы предпочтительнее, так как вы узнаете об ошибке быстрее. Для этого есть boost::noncopyable, или вы можете получить из базового класса, который скрывает свой конструктор копирования и назначения.

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

+0

Спасибо, это действительно хороший ответ. До сих пор я много использовал Java, изучая много концепций ООП с ней, и, вероятно, она впечатлила штамп на уме XP – doc