30

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

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

class B: public A {
    public:
        B() {
            A* f=new A();           // Why it is not working here
        }
};
4

4 回答 4

41

这与构造函数无关。这就是protected访问的工作方式。

访问说明符的工作方式protected,它允许派生类B访问基类对象的内容,A 只有当类A的对象是类的子对象时B。这意味着您在代码中唯一能做的就是访问A through 的内容:您可以通过 type 的指针(或 type 的引用)B访问 的成员。但是您不能通过类型(或引用)的指针访问相同的成员。AB *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
  }
};

在上面B::foo,您可以A::i使用简单的i语法访问基本成员。这相当于使用this->i语法。两者都可以,因为指针this具有 type B *,即您正在访问A::i一个 type 的指针B *。这正是protected访问说明符应该允许的。通过pb指针访问也是出于同样的原因。

但是,当您将this指针“转换”为 typeA *时,您将无法再A::i通过该新指针进行访问,即使您仍在尝试访问它们与以前相同的成员。

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

于 2010-03-06T17:55:35.730 回答
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!
   }
};

如下所示直接调用构造函数会在 gcc 版本 4.1.2 中为您提供以下错误:

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

test.cpp:4: error: A::A() is protected

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

   B() : A() // allowed to access constructor like this

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

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

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

于 2010-03-06T17:19:12.790 回答
0

让我分步回答:

1)构造函数不会被继承,这就是为什么在派生类中,它们不能被覆盖。
2) 构造函数被调用而不被调用。
3) 如果你在 A 中声明了一个简单的函数,比如 protected void print(),然后尝试在 B 中调用它,它就会起作用。这发生在 bcoz 中,B 继承了这个函数。

4) 当您执行类似 b : a() 的操作时,您正在调用构造函数,这是允许的。
5)尝试让 B 成为 A 的朋友类,然后运行,看看它是否有效。

希望这可以帮助。

于 2010-03-06T18:27:47.737 回答
0

我有同样的问题,这个链接让我很清楚。

cppreference是这样说的:

Protected members form the interface for the derived classes (which is   

distinct from the public interface of the class). 

A protected member of a class Base can only be accessed 

1) by the members and friends of Base 

2) by the members and friends (until C++17) of any class derived from Base, but only when operating on an object of a type that is derived from Base (including this)
于 2017-12-04T00:54:04.833 回答