12

不允许在派生类中调用受保护的构造函数,如此所述。

接受的答案解释说,仅当 class的对象是 class 的子对象时才protected授予对基类对象成员的访问权限。到目前为止,一切都很好。AAB

但是,为什么允许(至少在 GCC 4.6.3 中)调用静态保护方法?具体来说,以下编译对我来说没有任何意义,而注释行则没有:

class A 
{
protected:
    A() {}
    static A makeA() { return A(); }
};

class B: public A
{
public:
    static A makeAFromB()
    {
        return makeA(); // compiles
        // return A();  // does not compile
    }
};

从哲学上讲,构造函数非常像返回类对象的静态方法A,这就是为什么我在这里没有得到行为差异的原因。

4

3 回答 3

11

但是,为什么允许(至少在 GCC 4.6.3 中)调用静态保护方法?

因为这就是标准所说的。适用于成员可访问性的约束protected(并且您链接的答案很好地解释了)在 C++11 标准的第 11.4/1 段中定义,其第一句指定:

当非静态数据成员或非静态成员函数是其命名类 (11.2) 的受保护成员时,将应用超出第 11 条中所述的附加访问检查。[...]

附加访问检查不适用于静态成员或静态成员函数。

于 2013-06-04T09:01:41.543 回答
2

没错,protected 仅授予对嵌入式基础对象的访问权限的方式可能令人惊讶……但这是有充分理由的。假设您有几个派生自 的类Base,并且其中一个类中的一个方法想Base通过一些引用或指针对任意对象执行操作......可能Base它正在摆弄的是另一个派生链的一部分,它有其他行为期望Base考虑到它对受保护的成员函数的使用,对象。您正在有效地删除另一个派生类的预期封装,防止它强制执行预期的不变量,走出良好 OO 行为的世界......将这种洞察力应用于您的特定场景,C++ 规则阻止您使用受保护的构造函数当实际上没有派生对象嵌入该Base对象时,创建一个预期具有由某个派生类管理的不变量的子对象。

另外,protected构造函数的工作方式具有明确的效用 - 它阻止类的构造(使用该构造函数),除非作为派生类的子对象或基类的成员函数(例如makeA在您的示例中) - 无论它们'重新静态或非静态成员函数无关紧要......所有成员函数总是对类充满。

忽略静态成员函数private//的直观含义有什么用protectedpublic您是说您希望它们实际上是私有的,如果这是您想要的行为,那么只需将它们设为私有/如果您需要它们可访问,请将它们保护起来。显然,根据我第一段中的理由,受保护的访问受到限制。

于 2013-06-04T09:12:02.860 回答
0

静态方法是继承的,因为它们在子类的方法中可用。我们可以使用子类的名称调用静态方法,或者使用子类的实例,或者在子类的主体中没有限定。

于 2013-06-04T09:12:21.460 回答