Можно ли объяснить, почему это не позволяется,
#include <stdio.h>
class B {
private:
int a;
public:
int a;
};
int main() {
return 0;
}
в то время как это?
#include <stdio.h>
class A {
public:
int a;
};
class B : public A{
private:
int a;
};
int main() {
return 0;
}
И в случаях, у нас есть одна общественность и в одна названная частная переменная a
в class B
.
отредактированный теперь!
В обоих случаях у нас есть один общедоступный и одна частная переменная с именем a in класс B.
Нет, это неправда.
В первом случае у вас не может быть двух идентификаторов с одинаковыми именами в одной и той же области. Во втором случае B :: a
скрывает A :: a
, и для доступа к A :: a
вы должны полностью указать имя:
b.a = 10; // Error. You can't access a private member.
b.A::a = 10; // OK.
Класс B в первом примере недопустим, поскольку C ++ не может различать элементы по их спецификаторам доступа (общедоступный / частный / защищенный). Однако пространства имен - это способ для C ++ различать члены. В классе B во втором коде у вас нет «публичного a» и «частного a», у вас есть B :: a
и A :: a
.
Даже если бы было разрешено объявление членов с одним и тем же именем / подписью с разными спецификаторами доступа, не было бы возможности обратиться к правильному члену.
Потому что B :: a
скрывает A :: a
во втором примере. Вы все еще можете получить к нему доступ, но для того, чтобы компилятор понял, что вы запрашиваете член родительского класса с таким же hame, требуется явная квалификация.
В первом примере оба a
находятся в одной области, а во втором примере области разные.
Первое недопустимо, поскольку приводит к неоднозначным определениям. Во втором случае, хотя у вас есть как общедоступная, так и частная a
целочисленная переменная, вы скрыли A :: a внутри своего класса B. Компилятор неявно знает, что вы хотите, потому что есть способ явно получить доступ к скрытым переменным.
Я также считаю, что все сводится к манипулированию именами: спецификаторы хранилища не входят в состав фактического имени. Однако я могу ошибаться в этом.
Самый простой способ проиллюстрировать, почему одно разрешено, а другое - нет, - это посмотреть, как компилятор скомпилирует функцию-член, которая использует каждую переменную.
Внутри вашего класса b:
class b {
int a;
public:
int a;
void myMethod()
{
a = 10; //what a should the compiler use? Ambiguous, so the compiler sez BZZT.
}
}
Для 2-го примера:
class A
{
public:
int a;
}
class B: public A
{
private:
int a;
void someMethod()
{
a = 10; //implied that you are using B::a (which may be a programmer error)
}
}