Является ли публичный конструктор абстрактного класса кодовым кодом? Обеспечение защиты конструктора обеспечивает весь доступ, доступ к которому вы можете использовать. Единственным дополнительным доступом, который делает его общедоступным, было бы разрешить экземпляры класса объявляться как переменные в областях, которые не могут получить доступ к его защищенным членам, но экземпляры абстрактных классов не могут быть объявлены вообще.
Является ли публичный конструктор абстрактного класса кодовым кодом?
Ответ 1
Мое мнение состояло бы в том, что публичный конструктор может считаться запутанным, и, как вы говорите, его защита будет правильной. Я бы сказал, что защищенный конструктор правильно усиливает впечатление, что единственное разумное использование абстрактного класса должно вытекать из него.
Фактически, вам нужно только объявить конструктор в абстрактном классе, если ему нужно что-то сделать, например. инициализировать своих частных членов. Тогда я ожидал, что там будут другие защищенные функции-члены, которые полезны для производных классов.
EDIT:
Поскольку никто не опубликовал какой-либо код, а @sbi попросил кого-нибудь в комментарии к OP, я подумал, что отправлю некоторые из них:
class Base:
{
public: // The question is: should the ctor be public or protected?
// protected:
Base():i(0){} // ctor is necessary to initialise private member variable
public:
virtual ~Base(){} // dtor is virtual (but thats another story)
// pure virtual method renders the whole class abstract
virtual void setValue(void)=0;
protected:
int getValue(void){ return i;}
private:
int i;
};
Base b1; // Illegal since Base is abstract, even if ctor is public
Base& b2=makeBase(); //We can point to, or refer to a Base
b2.setValue(); // We're not sure what this does, but we can call it.
b2.getValue(); // Illegal since getValue is protected
Ответ 2
Я прочитал его, по крайней мере, в одном руководстве по кодированию, что конструкторы абстрактных классов не должны быть общедоступными - я думаю, что правило имеет смысл по той причине, что вы дали.
Однако, я не могу представить, чтобы сценарий, делающий его общедоступным, приводил бы к ошибкам. Поэтому я бы не стал так говорить, что это запах кода. Я вижу защищенный конструктор как свойство "приятно иметь":)
Ответ 3
Как вы говорите, нет необходимости предоставлять публичный конструктор абстрактного класса, и его нельзя использовать неправильно, если вы предоставляете публичный конструктор.
Однако вы можете рассматривать объявление конструктора как общедоступное как рекомендацию для структурирования классов, полученных из абстрактного.
Ответ 4
Абстрактный класс никогда не может быть непосредственно создан из-за чистых виртуальных методов, которые он объявляет. Таким образом, объявление конструктора как защищенного просто добавляет дополнительные советы для программистов.
Я видел рекомендацию объявить конструктор как защищенный здесь, в руководстве по стилю Google. И я встречал аналогичные рекомендации в некоторых других стандартах корпоративного кодирования. Таким образом, это выглядит как хорошая практика.
Ответ 5
Я знаю, что люди, очевидно, не согласны, но я не думаю, что абстрактные классы ctor должны быть защищены, если только интерфейс, который вы проектируете, не имеет конкретной причины для всех производных классов иметь также защищенный ctor.
Причина в том, что при разработке абстрактного класса вы разрабатываете интерфейс, который будет реализован классами-получателями. Производные классы должны реализовывать интерфейс точно так же, как и в базовом классе. Интерфейс, представленный абстрактным базовым классом, является контрактом; не нарушайте этот контракт.
Или, другими словами, если вы меняете интерфейс, почему вы в первую очередь получаете этот класс?
Это немного религиозный ответ, но что, черт возьми.; -)
Ответ 6
Ответ для современного C++
Однако я наталкиваюсь на старую ветку:
- это первый вопрос, который возник у меня при поиске разницы между
public
иprotected
конструкторами в абстрактных классах, - новые стандарты C++, опубликованные после того, как на этот вопрос был задан и дан ответ, изменили "правильный" ответ.
Резюме
public
конструкторы в абстрактных классах не являются запахом кода. Из-за того, как работают модификаторы доступа унаследованных конструкторов, наличие public
и protected
конструктора не эквивалентно. public
конструкторы в абстрактных классах добавляют больше прав доступа, чем protected
.
объяснение
В проекте стандарта N4659, 10.3.3/19 указано, что:
Синоним, созданный объявлением использования, имеет обычную доступность для объявления члена. Использование-декларатор, который называет конструктор, не создает синоним; вместо этого дополнительные конструкторы доступны, если они будут доступны при использовании для создания объекта соответствующего базового класса, а доступность объявления using игнорируется.
Это поведение было введено вместе с использованием-деклараторов в C++ 11, подробнее см. Этот вопрос.
Вот минимальный пример [ Godbolt ]:
class AbstractPublicCtor {
public:
virtual void foo() = 0;
AbstractPublicCtor(int) {}
};
class AbstractProtectedCtor {
public:
virtual void foo() = 0;
protected:
AbstractProtectedCtor(int) {}
};
class PublicCtor : public AbstractPublicCtor {
public:
using AbstractPublicCtor::AbstractPublicCtor;
void foo() override {}
};
class ProtectedCtor : public AbstractProtectedCtor {
public:
using AbstractProtectedCtor::AbstractProtectedCtor;
void foo() override {}
};
int main() {
PublicCtor x(5); // works
ProtectedCtor y(6); // fails to compile
}
Практическое правило
- Используйте
public
конструкторы, если у разработчиков абстрактного класса должны бытьpublic
конструкторы, а конструктор базового класса является подходящим кандидатом дляpublic
конструктора реализатора. - В противном случае используйте
protected
конструкторы (например, когда конструкторы создаются с использованием фабрики).
Примечание: это моё личное мнение, я с удовольствием его обсуждаю в комментариях.
Ответ 7
Я бы сказал, что это плохой признак по нескольким причинам.
Во-первых, он может ввести кого-то в заблуждение, думая, что они могут называть эту процедуру.
Во-вторых, это означает, что автор думал, что вы можете его назвать. Теперь вы не знаете, было ли это важной частью его дизайна или нет.
Ответ 8
Будьте осторожны, хотя явным образом объявляю/определяю ваш защищенный/закрытый конструктор копирования. Если вы этого не сделаете, компилятор сделает это за вас. См. Scott meyers эффективный С++, пункт 6.