ООП. Вопросы применения - страница 15

 

Конструктор по умолчанию имеет специальное назначение при инициализации массива объектов своего класса. Конструктор, все параметры которого имеют значения по умолчанию, не является компьютером по умолчанию. Тут.

Красным описку выделил.

Кстати, почему такой конструктор не является конструктором по умолчанию? Очередной костыль?

 
TheXpert:

Конструктор по умолчанию имеет специальное назначение при инициализации массива объектов своего класса. Конструктор, все параметры которого имеют значения по умолчанию, не является компьютером по умолчанию. Тут

Интересная опечатка, спасибо. Исправили.
 
Yedelkin:

"Invalid pointer access" == "Попытка к обращения к некорректному указателю"?

Зачастую прямой признак кривости рук или непонимания базовых принципов работы с указателями.

Реже признак плохой документированности использования класса.

 
TheXpert:

Кстати, почему такой конструктор не является конструктором по умолчанию? Очередной костыль?

Совсем наоборот. Костылём является наличие параметров по умолчанию, так как это является источником трудноуловимых багов. Здесь мы как раз проявили строгость.

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

 
stringo:

Костылём является наличие параметров по умолчанию, так как это является источником трудноуловимых багов.

Да как-то что-то не могу придумать таких ситуаций.

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

А, тогда нормально и логично. А то какая-то непонятная двойственность получалась.
 

Прочитал про операцию разрешения контекста ( :: ). Решил попробовать использовать её в двух неродственных классах:

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_B;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_A
  {
public:
   C_B              *pointer;

                     C_A(void) {};
                    ~C_A(void) {};
   void funcA(int i) { Print("funcA(",i,")=",i); }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_B
  {
public:
                     C_B(void) {};
                    ~C_B(void) {};
   void funcB(int j)
     {
      Print("funcB(",j,")=",j);
      C_A::funcA(j);
     }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   C_A object;
   object.pointer=new C_B();
   object.pointer.funcB(5);
   delete object.pointer;
  }

Компилятор выдаёт ошибку на строчке C_A::funcA(j). Если её закомментировать, то вроде работает. В чём моя ошибка?

 
Yedelkin:

Прочитал про операцию разрешения контекста ( :: ). Решил попробовать использовать её в двух неродственных классах:

Компилятор выдаёт ошибку на строчке C_A::funcA(j). Если её закомментировать, то вроде работает. В чём моя ошибка?

В вашем случае контекст класса C_A недоступен из класса C_B.

Это корректно только если:

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_B : public C_A
  {
public:
                     C_B(void) {};
                    ~C_B(void) {};
   void funcB(int j)
     {
      Print("funcB(",j,")=",j);
      C_A::funcA(j);
     }
  };

Но тогда можно:


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_B : public C_A
  {
public:
                     C_B(void) {};
                    ~C_B(void) {};
   void funcB(int j)
     {
      Print("funcB(",j,")=",j);
      funcA(j);
     }
  };


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


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_B;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_A
  {
public:
   C_B              *pointer;

                     C_A(void) {};
                    ~C_A(void) {};
   void func(int i) { Print("C_A::func(",i,")=",i); }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class C_B : public C_A
  {
public:
                     C_B(void) {};
                    ~C_B(void) {};
   void func(int j)
     {
      Print("C_B::func(",j,")=",j);
      C_A::func(j);
     }
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   C_A object;
   object.pointer=new C_B();
   object.pointer.func(5);
   delete object.pointer;
  }

Примерно так.

 
uncleVic:

В вашем случае контекст класса C_A недоступен из класса C_B.

Спасибо. Значит, ошибался, что операцию разрешения контекста можно применять и без наследования.
 

Пробую передать значения членов из одного класса в другой "по ссылке" и с помощью описателя. Вроде получаются оба варианта. Вот простейшая схема:

class B
  {
private:
   double            d1;
public:
                     B(double &d) {  d1=d; Print("class B, double d1=",d1);  };
                    ~B(void){};
  };
class A
  {
public:
   double            double_var;
   A                *pointerA;
 

                     A(void) : double_var(1.234567),pointerA(NULL) { SetPointer(); };
                    ~A(void) {if(CheckPointer(pointerA)==POINTER_DYNAMIC) delete pointerA; };
private:
   void SetPointer(void) { pointerA=GetPointer(this); }
  };
class C 
  {
public:
   A                *pointerA_C;
public:
                     C(void) : pointerA_C(NULL) {};
                    ~C(void) {if(CheckPointer(pointerA_C)==POINTER_DYNAMIC) delete pointerA_C;};
   void Printer() {if(CheckPointer(pointerA_C)!=POINTER_INVALID) Print("class C, double =",pointerA_C.double_var); };
  };
void OnStart()
  {
   A objA;
//---передаём значение double-переменной по ссылке
   B objB(objA.double_var);
//---передаём значение double-переменной через описатель
   C objC;
   objC.pointerA_C=objA.pointerA;
   objC.Printer();
  }

 Какой из этих двух способов работает быстрее? Какой предпочтительнее?

 
Yedelkin:

Пробую передать значения членов из одного класса в другой "по ссылке" и с помощью описателя. Вроде получаются оба варианта. Вот простейшая схема:

 Какой из этих двух способов работает быстрее? Какой предпочтительнее?

Что, совсем тяжёлые/некорректные вопросы?

Долгое время использовал первый способ ("по ссылке"), но вот мысль про описатели очень понравилась. Только не знаю, стоит ли из-за неё переписывать все классы.