2015-05-01 3 views
0

Я действительно путаться в следующих примерах:уточнение инициализации в C++

#include <iostream> 
class C { 
    public: 
    int a,b; 
}; 
int main() { 
    C c{3,6}; 
    std::cout<<c.a<<'\n'; 
    std::cout<<c.b<<'\n'; 
    return 0; 
} 

Он отлично работает и дает ожидаемый результат. Но если я изменю приведенный выше код, как показано ниже.

#include <iostream> 
class C { 
    int a,b; 
    public: 
     int get_a(){ 
      return a; 
     } 
     int get_b(){ 
      return b; 
     } 
}; 
int main(){ 
    C c{3,6}; 
    std::cout<<c.get_a()<<'\n'; 
    std::cout<<c.get_b()<<'\n'; 
    return 0; 
} 

В приведенном выше компиляторе программы показаны многочисленные ошибки. Почему единая инициализация разрешена в первой программе, но не во второй? Где я ошибаюсь?

+1

Во втором случае переменные-члены класса являются «частными» (неявно) и не могут быть доступны для прямого инициализации. –

+1

В общем: ошибки должны указывать, что не так ... часто бывает полезно их показать. Но в частности - вы изменили данные с публичного на частный. – Useless

+0

@Mat: Если я добавлю параметризованный ctor, тогда он отлично работает. Компилятор жалуется, что не существует подходящей функции для вызова «C :: C (<список с иничиатором с прикрепленным скобками>)» – Destructor

ответ

3

По умолчанию C++ class члены являются private, так не указав, что вы получаете приватную переменную. Потому что вы сделали тип частным вы не получите агрегированную инициализацию бесплатно больше, так что вы должны написать свой собственный конструктор для этого класса:

class C{ 
    C(int _a, int _b): 
    a(_a), b(_b) 
    {} 
}; 

Вам просто нужно исправить пространства имен для cout и ваш код должен скомпилироваться: http://coliru.stacked-crooked.com/a/1d69f4f141d2bcd2

от стандарта:

[dcl.init.aggr] An aggregate is an array or a class with no user-provided constructors, no brace-or-equal-initializers for non-static data members, no private or protected non-static data members, no base classes, and no virtual functions

в первом коде вы только имели общие переменные, так код работал, потому что вы имели в совокупности, в результате чего переменная секретна, что вызвала проблему, потому что она больше не была агрегированной в соответствии с вышеприведенным определением.

1

a и b: private в вашем втором примере и поэтому недоступны вне класса.

1

Вам необходимо переместить линию int a,b; в область public:, как в первом примере.

Вы также должны std:: перед cout

#include <iostream> 
class C { 
    public: 
     int a,b;  //Make public 
     int get_a(){ 
      return a; 
     } 
     int get_b(){ 
      return b; 
     } 
}; 
int main(){ 
    C c{3,6}; 
    std::cout<<c.get_a()<<'\n'; //use namespace std:: 
    std::cout<<c.get_b()<<'\n'; //use namespace std:: 
    return 0; 
} 
1

В модифицированной версии кода, вы переместили public: метку так и члены данных a и b больше не общественности. Следовательно, на них нельзя ссылаться вне класса, даже неявно, с помощью списка инициализаторов.

1

Первый код работал, потому что члены данных a и b были общедоступными, поэтому к ним можно было получить доступ извне класса. Однако во втором коде они объявляются частными, поэтому к ним нельзя получить доступ извне класса. Либо объявлять их общественности еще раз, или использовать конструктор следующим образом (если вы все еще хотите их как частные):

C(int x,int y) // This is a parameterised constructor 
    { 
     a=x; 
     b=y; 
    } 

И инициализирует их C c(3,6);

+1

Обратите внимание, что вы все равно можете использовать синтаксис 'C c {3,6}' с этим конструктором. – shuttle87

+0

@ shuttle87: Дает мне ошибку: 'error: в C++ 98 'c' должен быть инициализирован конструктором, а не '{...}' |'. –

+1

В C++ 98 вам действительно нужно использовать синтаксис 'c (3,6)', в более поздних версиях C++ 0x и более поздней версией предпочтительным является использование синтаксиса унифицированной инициализации. В зависимости от компилятора/версии для этого может потребоваться допустимый флаг компилятора. – shuttle87

Смежные вопросы