Почему защищенный конструктор повышает ошибку этот этот код?

Один вопрос о защищенном конструкторе. Я узнал, что защищенный конструктор может использоваться в производном классе. То, как когда-либо, я нашел ниже код, имеет ошибку. Почему это происходит как это?

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

class B: public A {
    public:
        B() {
            A* f=new A();           // Why it is not working here
        }
};
29
задан Santosh Kumar 21 November 2015 в 16:13
поделиться

3 ответа

Это не имеет никакого отношения конкретно к конструкторам. Так работает защищенный доступ.

Как работает спецификатор доступа protected , он позволяет производному классу B получать доступ к содержимому объекта базового класса A только тогда, когда этот объект класс A является подобъектом класса B . Это означает, что единственное, что вы можете сделать в своем коде, - это получить доступ к содержимому от A до 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
  }
};

В приведенном выше B :: foo вы можете получить доступ к базовому члену A :: i , используя простой i синтаксис. Это эквивалентно использованию синтаксиса this-> i . Оба будут работать, потому что указатель this имеет тип B * , то есть вы обращаетесь к A :: i через указатель типа B * . Это именно то, что должен разрешать спецификатор доступа protected . Доступ через указатель pb работает по той же причине.

Однако, когда вы «конвертируете» этот указатель в тип A * , вы больше не можете получить доступ к A :: i через этот новый указатель, даже хотя вы все еще пытаетесь получить доступ к тому же члену, что и раньше.

При применении к конструкторам спецификатор доступа protected имеет очень специфический эффект: защищенный конструктор может использоваться только для инициализации подобъектов базового класса. Его нельзя использовать для инициализации автономных объектов (что вы и пытались сделать). Другими словами, защищенные конструкторы - это еще один способ реализовать концепцию абстрактного класса в C ++ (наряду с чистыми виртуальными методами). Если конструкторы вашего класса защищены, то ваш класс фактически абстрактный . Вы не можете использовать его для определения независимых объектов «извне». (Конечно, это не относится к друзьям, а также к самому классу).

42
ответ дан 28 November 2019 в 01:38
поделиться

Позвольте мне сформулировать свой ответ по шагам:

1) Конструкторы не наследуются, и поэтому в производном классе их нельзя переопределить.
2) Конструкторы вызываются, а не вызываются.
3) Если вы объявили простую функцию в A, скажем, protected void print (), а затем попытались вызвать ее в B, это сработало бы. Это происходит bcoz, B унаследовал эту функцию.

4) Когда вы делаете что-то вроде этого b: a (), вы вызываете конструктор, и это разрешено.
5) Попробуйте сделать B классом-другом для A, а затем запустите и посмотрите, работает ли это.

Надеюсь, это поможет.

0
ответ дан 28 November 2019 в 01:38
поделиться

Когда базовый класс имеет защищенный конструктор, вы не можете создать экземпляр класса напрямую. Но вы можете сделать это, чтобы вызвать конструктор из конструктора базового класса:

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. Однако, если вы объявляете конструктор protected в C ++, вы не можете создать экземпляр этого класса, кроме как посредством наследования или дружеских отношений.

7
ответ дан 28 November 2019 в 01:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: