У меня два вопроса
1) Почему мы можем указать значение по умолчанию, если член является общедоступным, а когда он является частным, нам не разрешено? Возьмите пример ниже:
#include <iostream>
using namespace std;
class Test
{
private:
int a=5;
public:
Test()
{
cout<<a<<endl;
cout<<"default const";
a=0;
}
};
int main()
{
Test x;
cout<<x.a;
}
Для этого мы получаем ошибку ниже:
Compile Errors :
prog.cpp: In function 'int main()':
prog.cpp:6:11: error: 'int Test::a' is private
int a=5;
^
prog.cpp:19:13: error: within this context
Если я сделаю это общедоступным, как показано ниже:
#include <iostream>
using namespace std;
class Test
{
public:
int a=5;
Test()
{
cout<<a<<endl;
cout<<"default const";
a=0;
}
};
int main()
{
Test x;
cout<<x.a;
}
Мы получаем результат как:
5
default const0
2) Мой следующий вопрос: почему у нас такое поведение? Также, когда мы предоставляем это значение по умолчанию, почему значение конструктора переопределяет значение по умолчанию, предоставленное в классе?
Поскольку вы пытаетесь получить к нему доступ из main, компилятор просто сообщает вам, какое объявление переменной является проблемой (это просто включает инициализацию).
Мета-комментарий: этот вопрос не о «различном поведении»: поскольку один из двух примеров плохо сформирован, он недействителен C++ и вообще не «ведет себя». «Различное поведение» обычно означает, что две вещи компилируются и запускаются, но при одних и тех же входных данных производят разные наблюдаемые эффекты.
Возможный дубликат Что такое общедоступное, частное и защищенное в объектно-ориентированном программировании?
Я не думаю, что это настоящее полное сообщение об ошибке от вашего компилятора.
Член является частным, вы получаете сообщение об ошибке, когда пытаетесь его распечатать, вне класса.
Достаточно просто, сначала присваиваются все значения по умолчанию (конструируются, см. Комментарий), затем выполняется код внутри конструктора. Вот почему вы видите 5
внутри конструктора.
Если вы хотите, чтобы конструктор изменил значение инициализации a
, вы можете использовать список инициализаторов:
Test(): a{0}
{
cout<<a<<endl;
cout<<"default const";
}
И это напечатает 0
, значение a
никогда не будет 5
при использовании этого конструктора.
«значения по умолчанию присваиваются» - нет, значения по умолчанию не присваиваются (значения по умолчанию строятся). Вы можете увидеть это здесь coliru.stacked-crooked.com/a/26f3951020f96db3 Это небольшая формальность, но я думаю, что о ней стоит упомянуть.
Да, ты прав. Я отредактировал свой ответ. Я просто хотел, чтобы ответ был простым, но я полагаю, что он должен быть максимально точным: P
Мы также можем присвоить значение частным переменным-членам, но кажется, что вы обращаетесь к частной переменной-члену a
вне класса, что недопустимо.
К (2) и, в частности, «почему»: инициализаторы в классе действуют как дефолт, которые не зависят от каких-либо входных данных, переданных конструкторам, тогда как инициализаторы конструкторов можно рассматривать как специализацию. Представьте себе класс с 10 конструкторами, всем требуется одно и то же статическое значение для x
, вы должны придерживаться инициализаторов внутри класса, чтобы избежать избыточного кода.
Сообщение об ошибке немного вводит в заблуждение; проблема в вашем использование. Объявление было показано вам для контекста, и поскольку объявление включает инициализатор, это похоже, ошибка связана с этой инициализацией. Но это не так.
Итак, у нас нет такого поведения.
Что касается того, почему присвоение значения члену "переопределяет" ваше инициализированное значение, ну, это то, что делает присвоение. Когда вы инициализируете что-то, оно получает значение, а затем, когда вы назначаете ему позже, теперь вместо этого оно имеет значение что. Это то же самое, что и простая локальная переменная:
int x = 42;
x = 3;
Какую ценность сейчас имеет x
?
Код в теле конструктора - «позже». К моменту его запуска все инициализации участников (будь то по умолчанию или с указанными вами значениями) уже завершены.
Ошибка, которую вы видите, отсутствует в конструкторе класса и не имеет ничего общего со значениями по умолчанию. Ошибка возникает в выражении
cout << x.a
. И это демонстрирует всю цель контроля доступаpublic
/private
.