Как ни странно, но многое мне самому разъяснила книга Стефана Р. Дэвиса "C++ для чайников". Автор как-то ясно и доходчиво объясняет сложности языка. Можете там прочитать про конструкторы по умолчанию. Дело в том, что для обеспечения совместимости с уже существующими исходными кодами на языке C, в котором нет понятия "конструктор", компилятор C++ сам создает конструктор без параметров, который обнуляет все члены класса, если программист не определит его явно. Он называется конструктором по умолчанию. Если же хоть какой-то конструктор уже объявлен (не важно с параметрами или без), то компилятор, обнаружив это не станет создавать конструктор по умолчанию. То есть, если вы объявите конструктор с параметрами и создадите экземпляр класса, не указав параметры, то при компиляции получите ошибку. Ведь компилятор обнаружил уже конструктор с параметрами, значит, он не будет генерировать конструктор по умолчанию (без параметров). И если вам нужен конструктор без параметров, вы должны определить его явно.
Резюмируем:
1) Компилятор проверяет, определен ли явно хоть какой-нибудь конструктор. Если таковой имеется, компилятор не создает конструктор по умолчанию.
2) Если у вас уже определен конструктор с параметрами, но так же необходим конструктор без параметров, вы должны определить явно (сами) конструктор без параметров.
Теперь код.
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
cout << "Default constructor tutorial application" << endl;
cout << "Type any key for quit..." << endl;
getch();
return 0;
}
В вашем IDE создайте проект консольного приложения "tutorial01_default_constructor", например. В проекте создайте файл "main.cpp", в который скопируйте вышележащий код.
Объект "cout" служит для вывода текста в окно консоли приложения. Для его работы нужен заголовочный файл "iostream".
Функция getch() возвращает ASCII код символа из буфера клавиатуры. Если буфер клавиатуры пуст, программа переводится в режим ожидания. Зачем это нужно. Если вы удалите строку с вызовом getch() и скомпилируете, а потом запустите приложение, компьютер молниеносно обработает ваши несколько инструкций и в конце по оператору return завершит приложение - вы успеете заметить только мелькнувшее окошко, которое исчезнет сразу как появится.
Добавим класс MyData.
MyData.h
#ifndef MYDATA_H
#define MYDATA_H
class MyData
{
public:
int m_n;
};
#endif // MYDATA_H
Явного задания конструктора нет как видно.
MyData.cpp
#include "MyData.h"
Добавим в код main.cpp:
#include <iostream>
#include <conio.h>
#include "MyData.h"
using namespace std;
int main()
{
MyData data;
cout << "Default constructor tutorial application" << endl;
cout << "data.m_n = " << data.m_n << endl;
cout << "Type any key for quit..." << endl;
getch();
return 0;
}
Компилируем и ...
Внимание! Если вы хотите, чтобы конструктор наверняка обнулил какие-то члены класса, пропишите это явно. У меня, в проекте в IDE "Code::Blocks" компилятор MinGW не выдал никаких ошибок и, видимо создал конструктор по умолчанию, но не обнулил член m_n. Хотя конструктор и правда был создан неявно самим компилятором.
Теперь добавим конструктор с параметром, но в функции main создание объекта data класса MyData оставим прежним, т.е. ничего не трогаем.
MyData.h
#ifndef MYDATA_H
#define MYDATA_H
class MyData
{
public:
MyData(int n);
int m_n;
};
#endif // MYDATA_H
MyData.cpp
#include "MyData.h"
MyData::MyData(int n)
{
m_n = n;
}
При компиляции будет ошибка. Ведь один конструктор (а именно конструктор с параметром) уже есть и компилятор, заметив это, не будет создавать больше никакой конструктор.
Ок. Добавьте его явно (сами).
MyData.h
#ifndef MYDATA_H
#define MYDATA_H
class MyData
{
public:
MyData();
MyData(int n);
int m_n;
};
#endif // MYDATA_H
MyData.cpp
#include "MyData.h"
MyData::MyData()
{
m_n = 0;
}
MyData::MyData(int n)
{
m_n = n;
}
Компилируем. Все нормально.