为什么受保护的构造函数会引发此代码的错误?

sky*_*oor 29 c++ constructor protected

关于受保护构造函数的一个问题 我了解到受保护的构造函数可以在派生类中使用.但是,我发现下面的代码有错误.为什么会这样?

class A
{
    protected:
        A(){}
};

class B: public A {
    public:
        B() {
            A* f=new A();           // Why it is not working here
        }
};
Run Code Online (Sandbox Code Playgroud)

AnT*_*AnT 42

这与构造函数无关.这就是protected访问的工作原理.

的方式protected访问指示符的工作原理,它允许派生类B访问基类的一个对象的内容A 只有当类的该对象A是类的一个子对象B.这意味着您在代码中唯一能做的就是访问A through 的内容B:您可以A通过类型指针B *(或类型的引用B &)访问成员.但是您无法通过类型A *(或引用A &)的指针访问相同的成员.

请考虑以下示例

class A {
protected:
  int i;
};

class B : A  {
  void foo() {
    i = 0;        // OK
    this->i = 0;  // OK

    B *pb = this;
    pb->i = 0;    // OK

    A *pa = this;
    pa->i = 0;    // ERROR

    ((A *) this)->i = 0; // ERROR
  }
};
Run Code Online (Sandbox Code Playgroud)

在上面B::foo,您可以A::i使用简单的i语法访问基本成员.这相当于使用this->i语法.两者都可以工作,因为指针this有类型B *,即你通过A::i类型的指针访问B *.这正是protected访问说明符应该允许的内容.通过pb指针访问的原因完全相同.

但是,当您将this指针"转换" 为类型时A *,A::i即使您仍在尝试访问与之前完全相同的成员,也无法再通过该新指针进行访问.

当应用于构造函数时,protected访问说明符具有非常特定的效果:受保护的构造函数只能用于初始化基类子对象.它不能用于初始化独立对象(这是您尝试执行的操作).换句话说,受保护的构造函数是在C++中实现抽象类概念的另一种方法(以及纯虚方法).如果你的类的构造函数受到保护,那么你的类就是有效的抽象.您不能使用它来"从外部"定义独立对象.(当然,以上内容不适用于朋友,也不适用于班级内部).


Jam*_*son 7

当基类具有受保护的构造函数时,您无法直接实例化该类.但是你可以这样做从基类构造函数中调用构造函数:

class A {

protected:
   A() {}
};

class B: public A {
public:
   B() : A() // allowed to access constructor like this
   {
      A* f = new A(); // Not allowed to access constructor like this!
   }
};
Run Code Online (Sandbox Code Playgroud)

如下所示直接调用构造函数会使gcc版本4.1.2出现以下错误:

      A* f = new A(); // Not allowed to access constructor like this!

test.cpp:4: error: A::A() is protected
Run Code Online (Sandbox Code Playgroud)

但是,您对构造函数的调用没有错误:

   B() : A() // allowed to access constructor like this
Run Code Online (Sandbox Code Playgroud)

这背后的原因是第二个调用通过继承访问A()构造函数,这是允许的.但是,这会尝试通过直接调用构造函数显式创建A()的新实例:

      A* f = new A(); // Not allowed to access constructor like this!
Run Code Online (Sandbox Code Playgroud)

这可能看起来不直观,因为B应该能够访问A的构造函数,因为B继承自A.但是,如果声明在C++中受保护的构造函数,则除了通过继承或朋友关系之外,不能创建该类的实例.

  • @James - 虽然您通常是正确的,但有两种方法可以使用受保护的构造函数创建类的实例.1)在同一类的成员函数内.2)在"朋友"中 (2认同)