Один вопрос о защищенном конструкторе. Я узнал, что защищенный конструктор может использоваться в производном классе. То, как когда-либо, я нашел ниже код, имеет ошибку. Почему это происходит как это?
class A
{
protected:
A(){}
};
class B: public A {
public:
B() {
A* f=new A(); // Why it is not working here
}
};
Это не имеет никакого отношения конкретно к конструкторам. Так работает защищенный
доступ.
Как работает спецификатор доступа 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 ++ (наряду с чистыми виртуальными методами). Если конструкторы вашего класса защищены, то ваш класс фактически абстрактный . Вы не можете использовать его для определения независимых объектов «извне». (Конечно, это не относится к друзьям, а также к самому классу).
Позвольте мне сформулировать свой ответ по шагам:
1) Конструкторы не наследуются, и поэтому в производном классе их нельзя переопределить.
2) Конструкторы вызываются, а не вызываются.
3) Если вы объявили простую функцию в A, скажем, protected void print (), а затем попытались вызвать ее в B, это сработало бы. Это происходит bcoz, B унаследовал эту функцию.
4) Когда вы делаете что-то вроде этого b: a (), вы вызываете конструктор, и это разрешено.
5) Попробуйте сделать B классом-другом для A, а затем запустите и посмотрите, работает ли это.
Надеюсь, это поможет.
Когда базовый класс имеет защищенный конструктор, вы не можете создать экземпляр класса напрямую. Но вы можете сделать это, чтобы вызвать конструктор из конструктора базового класса:
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 ++, вы не можете создать экземпляр этого класса, кроме как посредством наследования или дружеских отношений.