Есть простенькая программа на с++. Есть три класса, один содержит приватными полями 2 других. При вызове конструктора первого неявно вызываются конструкторы остальных. Вопрос почему? и что более важно, как этого избежать?
class Device
{
private:
Date date;
TypeSensor type;
int placeBinding;
Sensor sensor;
......
}
То есть при вызове конструктора девайс вызывается конструктор Date. Все бы ничего, но TypeSensor нужно инициализироват ранее, нежели остальные поля. Поэтому интересно есть ли способы решения этой проблемы.
enum TypeSensor {
ACCELEROMETER,
PROXYMETER,
TEMPERATURE
};
class Sensor
{
string unitOfMeasured;
int maximum;
int minimum;
float value;
.....
}
Порядок инициализации переменных определяется их следованием в объявлении класса. Переставьте в объявлении класса TypeSensor
и Date
, что бы TypeSensor
инициализировался первым.
class Device
{
private:
TypeSensor type;
Date date;
int placeBinding;
Sensor sensor;
}
Непонятно чего вы хотите избежать. При создании объекта, обязаны инициализироваться все поля класса. Если в объявлении класса стоит Date date;
то это поле обязано проинициализироваться при создании Device
.
Однако если вы хотите избежать вызова конструктора Date
то можно сделать указатель на него Date* date;
и выделить память в другом месте.
В языке С++ конструктор объекта класса всегда вызывает конструкторы всех его подобъектов. Так работает язык С++. Избежать этого нельзя.
Порядок инициализации подобъектов определятся видом подобъекта (базовый подобъект или подобъект-член) и порядком объявления подобъекта среди аналогичных подобъектов. В вашем случае требуемого вам порядка инициализации можно достичь просто переупорядочиванием объявлений членов класса.
Однако если вам нужен какой-то специфический порядок инициализации подобъктов, то лучше достичь его не манипуляциями с порядком объявления, а другими средствами. А именно: лучше отложить инициализацию всех или некоторых подобъектов, а затем выполнить ее вручную в требуемом вам порядке. Этого можно достичь разными способами.
Можно сделать конструктор по умолчанию подобъекта ничего не делающим, а для фактической инициализации предоставить специальный метод.
Можно сделать агрегацию подобъектов не напрямую, а через умный указатель std::unique_ptr
.
Вместо агрегации объектов напрямую можно агрегировать std::optional
.
И т.д.
Никак не связано с вопросом, но у Вас SensorType
вынесен из класса Sensor
. Может быть есть смысл сделать SensorType
частью класса Sensor
и передавать его в конструктор?
Как-нибудь так, например:
class Sensor
{
public:
enum class Type{
DEFAULT = 0,
ACCELEROMETER = 0,
PROXYMETER = 1,
TEMPERATURE = 2
};
explicit Sensor(const Type& type = Type::DEFAULT):
m_unitOfMeasured{},
m_maximum{1},
m_minimum{0},
m_value{0.0},
m_type{type}
{
switch (m_type) {
case Type::ACCELEROMETER:
m_unitOfMeasured = "acceleration";
...
break;
case Type::PROXYMETER:
m_unitOfMeasured = "level";
...
break;
case Type::TEMPERATURE:
m_unitOfMeasured = "degree";
...
break;
default:
...
break;
}
}
private:
std::string m_unitOfMeasured;
int m_maximum;
int m_minimum;
float m_value;
Type m_type;
};
class Date{};
class Device
{
public:
Device(const Sensor::Type& sensorType = Sensor::Type::DEFAULT):
m_sensor{sensorType},
m_date{},
m_placeBinding{}
{}
private:
Sensor m_sensor;
Date m_date;
int m_placeBinding;
};
UPD. Ну тогда вот так как-то:
enum class SensorType{
DEFAULT = 0,
UNKNOW = 0,
ACCELEROMETER = 1,
PROXYMETER = 2,
TEMPERATURE = 3
};
class Sensor
{
public:
Sensor(const SensorType& type = SensorType::DEFAULT):
m_unitOfMeasured{},
m_maximum{1},
m_minimum{0},
m_value{0.0},
m_type{type}
{
switch (m_type) {
case SensorType::ACCELEROMETER:
m_unitOfMeasured = "acceleration";
break;
case SensorType::PROXYMETER:
m_unitOfMeasured = "level";
break;
case SensorType::TEMPERATURE:
m_unitOfMeasured = "degree";
break;
default:
break;
}
}
private:
std::string m_unitOfMeasured;
int m_maximum;
int m_minimum;
float m_value;
SensorType m_type;
};
class Date{};
class Device
{
public:
Device(const Date& date, const int placeBinding, const SensorType& sensorType= SensorType::DEFAULT):
m_type{sensorType},
m_sensor{sensorType},
m_date{date},
m_placeBinding{placeBinding}
{}
Device(const Device& other):
m_type{other.m_type},
m_sensor{other.m_sensor},
m_date{other.m_date},
m_placeBinding{other.m_placeBinding}
{
}
static Device createByUser(){
int n;
std::cout << "choise 1, 2 or 3 type of sensor: " << std::endl;
std::cout << "1. ACCELEROMETER" << std::endl;
std::cout << "2. PROXYMETER" << std::endl;
std::cout << "3. TEMPERATURE" << std::endl;
std::cin >> n;
if (n >= 1 && n <= 3){
return Device(Date(), 0, static_cast<SensorType>(n));
}else{
return Device(Date(), 0);
}
}
private:
SensorType m_type;
Sensor m_sensor;
Date m_date;
int m_placeBinding;
};
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
При создании сокета можно указать WSA_FLAG_OVERLAPPED, что это означает? В MSDN достаточно скудная информацияЧто это вообще за технология overlapped I/O operations...
Доброго времени суток! Как можно добавить картинку в текст, что бы было такое