Конструкторы по умолчанию, почему у моего класса три? Когда компиляторы обрабатывают классы как структуры? - PullRequest
3 голосов
/ 27 октября 2010

Я всегда думал, что есть только два значения по умолчанию construcors: конструктор без аргументов и копия construtor.

Но сегодня я написал что-то вроде этого:

Сначала я хотел убедиться, что в C ++ инициализация структур в c-стиле все еще действительна.

struct Foo{
    int a;
    bool b;
    char* c;
    double d;
};
//..
Foo arr[2]={{0, true, "a", 3.14}, {1, false, "z", 42.0}};

хорошо, это работает. Но затем я решил проверить, что произойдет после изменения struct на class.

class Bar{
 public:
    int a;
    bool b;
    char* c;
    double d;
};

//..

Bar arr[2]={{0, true, "a", 3.14}, {1, false, "z", 42.0}};//works
Bar bar;                                                 //works
Bar bar2=arr[1];                                         //works
//Bar bar3(2, false, "so", 7.0);                         //of course doesn't work
//first, second, third ways works... 

это компилируется, если class Bar не имеет никаких закрытых / защищенных полей (но может содержать методы). Таким образом, пока компилятор может создавать класс, который использует только простые свойства структур, он может быть скомпилирован.

  • Первый вопрос: я прав?

  • Второй вопрос: это функция компилятора (в данном случае gcc) или это именно то, что говорит Standard?

[EDIT]

код //Bar bar3(2, false, "so", 7.0); //of course doesn't work здесь не проблема;)


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

Ответы [ 7 ]

9 голосов
/ 27 октября 2010

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

Единственная разница между struct и class - это видимость членов по умолчанию и режим наследования по умолчанию.struct D : B { ... эквивалентно class D : public B { public: ....

3 голосов
/ 27 октября 2010

Ну, кажется нормальным, что "// Bar bar3 (2, false," so ", 7.0);"не работает, так как вы не определили конструктор с этой подписью.Чтобы это работало, вам нужно определить конструктор с этой сигнатурой в вашем классе.Компилятор генерирует только конструктор по умолчанию и конструктор копирования по умолчанию, если вы сами не объявите их.

2 голосов
/ 28 октября 2010

Хотя вы назвали это инициализацией в стиле C, ее официальное название - список инициализаторов.Только агрегаты могут быть инициализированы списками инициализаторов (см. 8.5 в стандарте).

Агрегат - это массив или класс с

  • без объявленных пользователем конструкторов,
  • нет личных или защищенных нестатических элементов данных,
  • нет базовых классов,
  • и нет виртуальных функций.

Это действительные ограничения, которые у вас есть.Это означает, что вы можете использовать списки инициализаторов с агрегатами без POD:

struct Aggregate
{
   std::string s;
};

Aggregate ag = { "hello" };
2 голосов
/ 27 октября 2010

С //Bar bar3(2, false, "so", 7.0); вы вызываете ctor, который не существует.

0 голосов
/ 27 октября 2010

Хорошо известно, что конструктор по умолчанию и конструктор копирования по умолчанию существуют для любого класса в C ++ независимо от того, объявлены они явно или нет.Я думаю, что происходит, когда вы используете следующий синтаксис:

Bar arr[2]={{0, true, "a", 3.14}, {1, false, "z", 42.0}}; 

Если компилятор определит тип объектов, затем вызовет конструктор по умолчанию для каждого объекта, а затем назначит каждому полю соответствующую его позиции в определении класса,Компилятор не может вызвать конструктор копирования по умолчанию, поскольку при создании нового объекта напрямую объекту того же типа не передается, то есть конструктор копирования должен вызываться в следующих сценариях:

Bar a;     //default constructor is called
Bar b(a);  //default copy constructor is called
Bar c = a; //default copy constructor is called

Чтовам нужно добавить конструкторы по умолчанию в класс Bar и затем выполнить отладку, чтобы узнать, что на самом деле происходит ...

0 голосов
/ 27 октября 2010

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

1. Да - вы правы относительно вышесказанного.

2.

Это функция компилятора (в данном случае gcc)

О какой «функции» вы говорите?Просто перегрузите ваш конструктор, чтобы иметь метод Bar :: Bar (int, bool, char *, double), и вы плавно ходите

0 голосов
/ 27 октября 2010

Бар соответствует требованиям типа POD, что означает, что его можно инициализировать как структуру C.Будучи классом или структурой, это никак не влияет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...