为什么允许在派生类中调用受保护的静态方法?

时间:2013-06-04 08:49:14

标签: c++ inheritance

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

接受的答案解释了protected仅当类A的对象是类A的子对象时才授予对基类B对象成员的访问权限。到目前为止,非常好。

但是,为什么允许(至少在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的对象的静态方法,这就是为什么我在这里没有得到行为差异的原因。

3 个答案:

答案 0 :(得分:10)

  

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

因为这就是标准所说的。适用于protected成员的可访问性的约束(以及您所链接的答案解释得非常好)在C ++ 11标准的第11.4 / 1节中定义,其第一句规定:

  

非静态数据时,会应用超出前面第11条所述的额外访问权限检查   成员或非静态成员函数是其命名类的受保护成员(11.2)。 [...]

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

答案 1 :(得分:2)

你是正确的,受保护的方式只允许访问嵌入式基础对象可能会令人惊讶......但这是一个很好的理由。假设您有一些派生自Base的类,并且其中一个类中的方法希望通过某个引用或指针对任意Base对象执行操作...可能是{{ 1}}它的摆弄是另一个派生链的一部分,它具有Base对象的其他行为期望,给出了它对受保护成员函数的使用。您有效地删除了其他派生类所期望的封装,阻止它强制执行预期的不变量,走出了良好的OO行为的世界......将这种洞察力应用于您的特定场景,C ++规则阻止您使用它当实际上没有嵌入Base对象的派生对象时,受保护的构造函数可以创建一个预期具有由某些派生类监管的不变量的子对象。

另外,Base对构造函数的工作方式有明确的实用性 - 它阻止构造类(使用该构造函数),除了作为派生类的子对象,或者从基类的成员函数(如在你的例子中是protected - 无论它们是静态成员函数还是非静态成员函数都是无关紧要的......所有成员函数总是对类完全有效。

忽略makeA / private / protected对静态成员函数的直观含义有什么用处?你说你期望它们实际上是私密的,如果你想要的那些行为然后只是让它们成为私人/如果你需要它们可以使它们受到保护。显然,根据我的第一段中的理由,受保护的访问受到限制。

答案 2 :(得分:0)

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