LINUX.ORG.RU

C++, порядок вызова инициализации переменной и вызова конструктора

 


0

2

Привет!

Наткнулся на проблему которую не могу решить.

Есть класс Class2Enh. При его инициализации надо сначала инциализировать свойство acltual_cl, а потом с объектом actual_cl вызвать конструктор базового класса. Если я пытаюсь сделать так:

#include<stdio.h>

class Class1
{
  protected:
    int some_property;
  public:
    Class1()  { some_property = 1;};
    virtual int getSomeProperty() {return some_property;};
};

class Class2Base
{
  protected:
    Class1 &cl;
  public:
//    Class2Base(Class1 & cl_to_use): cl(cl_to_use) {printf("Class2Base constructor\n"); };
    Class2Base(Class1 & cl_to_use): cl(cl_to_use) { printf("DEBUG2: class1's SomeProperty = %i\n", cl_to_use.getSomeProperty()); };

    virtual void Debug() {printf("DEBUG: class1's SomeProperty = %i\n",cl.getSomeProperty());};
};


class Class2Enh: public Class2Base
{
  protected:
    Class1 actual_cl;
  public:
    Class2Enh(): actual_cl (), Class2Base(actual_cl) {};
};


int main()
{
  Class2Enh tue;
  tue.Debug();
}

То получаю Segmentation Fault в конструкторе Class2Base при попытке обратиться к еще не инициализированному экземпляру actual_cl.

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

★★★

Ответ на: комментарий от anonymous

каф, не до копировалась строка до конца

anonymous ()

Нет, порядок записи в списке инициализации ни на что не влияет. Базовые классы все инициализируются до всех полей. Правильное решение - пересмотреть дизайн, чтобы не было такой странной зависимости. Если не получается - вынести это поле в другой базовый класс.

Begemoth ★★★★★ ()
Ответ на: комментарий от Begemoth

ага… Спасибо…

Ну вот у меня Class1 целая иерархия классов, которой оперирует другая иерархия, Class2.

При этом в Class2Base предполагалась решать общие задачи, вне зависимости от того какой из Class1 будет использоваться. А вот наследники Class2Base уже знают какой из множества Class1 им нужен, и реализовывают уже конкретную специфику…

Пока в качестве пересмотра дизайна, есть только идея уйти от наследования и внутри Class2Enh завести экземпляры Class2Base и нужный Class1. Скорее всего будет работать. Но как-то не спортивно…

shaplov ★★★ ()
Ответ на: комментарий от shaplov

Наоборот, правильная идея. Аггрегация вместо наследования — это хорошо и нужно.

Miguel ★★★★★ ()

facepalm, вместо изобретения CRTP

лучше купить учебник С++ и изучить наизусть

anonymous ()

Можно поле сделать optional и обращаться к нему через функцию, в ней инициализировать, если еще нет.

Но вобще в примере так делать не надо. Нужна виртуальная функция, которая будет возращать ссыль на объект, ее переопределяешь и готово.

Или, как вариант, вызываешь метод базового класса, который устанавливает нужное значение. Но это плохо, ибо конструирование в два этапа.

Еще можно тупо кучу задействовать. Потом получать наоборот, в потомке.

Вобще наследование подразумевает как раз, среди прочего, то, что дочерние классы строятся после базовых. Так уж вышло как бы :) так что ситуация не здоровая.

zerhud ()

Чего ты хочешь добиться? Выглядит страшно.

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

invy ★★★★★ ()

Множественное наследование?

class Class2Enh: protected Class1, public Class2Base
{
  protected:
    //Class1 actual_cl;
pavlick ★★ ()
11 июня 2021 г.

Class2Enh(): actual_cl (), Class2Base(actual_cl) {};

Class2Enh(): Class2Base(Class1()), actual_cl () {};


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

safocl ★★ ()
Последнее исправление: safocl (всего исправлений: 2 )
Ответ на: комментарий от shaplov

Наследование классов это устаревшая концепция. В современном коде используются очень редко. Пересматривай архитектуру своего кода.

anonymous ()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.