抽象类中的公共构造函数是一个代码吗?使构造函数受到保护可提供您可以使用的所有访问权限。公开提供的唯一额外访问权限是允许将类的实例声明为无法访问其受保护成员的范围中的变量,但是根本不能声明抽象类的实例。
答案 0 :(得分:12)
我已经在至少一个编码指南中读到它,抽象类的构造函数不应该公开 - 我认为这个规则对你给出的理由有意义。
然而,我无法想象将其公开会导致出错的情况。所以我不会说这是代码味道。我将受保护的构造函数视为“很好的”属性:)
答案 1 :(得分:4)
我的观点是,公共构造函数可能会被视为令人困惑,正如您所说,保护它是正确的。我会说受保护的构造函数正确地强化了这样一种印象,即抽象类的唯一合理用法是从它派生出来。
实际上,如果需要执行某些操作,您只需要在抽象类中声明构造函数,例如。初始化自己的私人成员。我希望有其他受保护的成员函数对派生类有用。
修改强>
由于没有人发布任何代码而且@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)
正如您所说,如果您提供公共构造函数,则无需提供抽象类的公共构造函数,也不会被滥用。
但是,您可以考虑将构造函数声明为公共结构,以便构造从抽象类派生的类。
答案 3 :(得分:3)
抽象类永远不能直接实例化,因为它声明了纯虚方法。因此,将构造函数声明为受保护只会为程序员添加额外的提示。
我看到建议在Google风格指南中将构造函数声明为受保护的here。我在其他一些公司编码标准中也遇到了类似的建议。所以这看起来是一种很好的做法。
答案 4 :(得分:2)
我知道很多人显然不同意,但我不认为应该保护抽象类ctor,除非你设计的接口有一个特定的原因,所有派生类也有一个受保护的ctor。
原因是当你设计一个抽象类时,你正在设计一个由派生类实现的接口。派生类应该完全按照基类中的设计实现接口。抽象基类提供的接口是契约;不要违反合同。
或者换句话说,如果您正在更改界面,那么为什么您首先从该类派生出来?
这是一个宗教回答,但是到底是什么。 ; - )
答案 5 :(得分:2)
我在这里碰到一个旧线程,但是:
public
和protected
构造函数之间的差异时遇到的第一个问题, public
构造函数不是代码气味。由于继承构造函数的访问修饰符的工作方式,使public
vs protected
构造函数不等效。 <{1}}抽象类中的public
构造函数添加了比protected
个更多的访问权限。
标准草案N4659,10.3.3 / 19指定:
由 using-declaration 创建的同义词具有通常的可访问性 对于成员声明。命名a的 using-declarator 构造函数不会创建同义词;相反,额外的 如果构造函数在以前可以访问它们,则可以访问它们 构造相应基类的对象,以及 忽略使用声明的可访问性。
此行为是与C ++ 11中的 using-declarators 一起引入的,有关详细信息,请参阅this question。
这是一个最小的例子[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
构造函数(例如,使用工厂构建实现者时)。注意:这是我个人的意见,我很高兴在评论中讨论它。
答案 6 :(得分:1)
出于几个原因,我说这是一个不好的迹象。
首先,它可能误导某人认为他们实际上可以称之为常规。
第二个是暗示作者认为你可以调用它。你现在不知道这是否是他设计的重要部分。