How many flows?
От: agrilya  
Дата: 12.06.03 08:57
Оценка:
Find as many flows as you can in the following code. Please describe each of them in detail.

class AbstractHandle
{
public:
  AbstractHandle()
  {
    connect();
  }
  ~AbstractHandle()
  {
    disconnect();
  }
protected:
  virtual void connect() 
  {
  }
  virtual void disconnect() 
  {
  }
};

class ConcreteHandle : public AbstractHandle
{
protected:
  virtual void connect()
  {
    if (MyAPIConnect() != API_OPERATION_OK)
      throw "Connection error.";
  }

  virtual void disconnect()
  {
    if (MyAPIDisconnect() != API_OPERATION_OK)
      throw "Disconnection error";
  }
};


Исправлена подсветка синтаксиса. -- ПК.
Re: How many flows?
От: Аноним  
Дата: 12.06.03 12:02
Оценка: :)
Здравствуйте, agrilya, Вы писали:

A>Find as many flows as you can in the following code. Please describe each of them in detail.


<...>

Я нашёл один.

1. flaw [дефект] пишется с буквой a, flow переводится как [поток,течение,].
Re[2]: How many flows?
От: Awaken Украина  
Дата: 12.06.03 12:15
Оценка:
А>1. flaw [дефект] пишется с буквой a, flow переводится как [поток,течение,].

а еще flow — поток выполнения программы. flowchart — блоксхема
т.е. how many flows тоже имеет смысл но совершенно другой
Re: How many flows?
От: onyXMaster Россия  
Дата: 12.06.03 12:30
Оценка:
Здравствуйте, agrilya, Вы писали:

Ну насчет in detail скучно, а вообще:
1. [критическая ошибка] вызов виртуального метода из конструктора
2. [плохой стиль] вызов виртуального метода из деструктора без обвязки
3. [критическая ошибка] невиртуальный деструктор в классе с явным полиморфным поведением (с учетом п.1 это неважно)
4. [логическая ошибка] объявление виртуальных методов интерфейса с использованием спецификации кода — если это именно интерфейс, то функции нужно было сделать чисто виртуальными
5. [ошибка] выброс исключения в методе, вызываемом в конструкторе без обязки в последнем (с учетом п.1 это неважно)
6. [критическая ошибка] выброс исключения в деструкторе, вызываемом в конструкторе без обязки в последнем
7. [плохой стиль] — выброс исключений неконкретизированного типа (const char*)
8. [плохой стиль] — просто по уродски выглядит — некрасивый код
-- onyXMaster
Re: How many flows?
От: Nose Россия  
Дата: 12.06.03 12:41
Оценка:
Здравствуйте, agrilya, Вы писали:

A>Find as many flows as you can in the following code. Please describe each of them in detail.


class AbstractHandle
{
public:
  AbstractHandle()
  {
    connect();
  }

protected:
  virtual void connect() 
  {
  }


А разве можно вызывать виртуальные функции в конструкторе? Кажись, vftable уще не создана...
... << RSDN@Home 1.0 beta 7a >>
Re[2]: How many flows?
От: Sergeem Израиль  
Дата: 12.06.03 15:04
Оценка:
Здравствуйте, onyXMaster, Вы писали:

XM>Здравствуйте, agrilya, Вы писали:


XM>Ну насчет in detail скучно, а вообще:

<snip>

XM>5. [ошибка] выброс исключения в методе, вызываемом в конструкторе без обязки в последнем (с учетом п.1 это неважно)


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

<snip>
Serge.

Hасколько проще была бы жизнь, если бы она была в исходниках.
Re[3]: How many flows?
От: Awaken Украина  
Дата: 12.06.03 16:12
Оценка:
S>А что такое обвязка, и почему плохо из конструктора исключения кидать?

объект не сконструируется полностью. соответственно не сможет быть удален деструктором. имеем мемори лик.
хорошо про это описано в Scott Meyers. More Effective C++
Re[4]: How many flows?
От: TepMuHyc  
Дата: 12.06.03 16:28
Оценка:
Здравствуйте, Awaken, Вы писали:

S>>А что такое обвязка, и почему плохо из конструктора исключения кидать?


A>объект не сконструируется полностью.

Ну и чудесно. Не вызовется деструктор для данного обьекта — все предельно справедливо.

A>соответственно не сможет быть удален деструктором.

Вообоще-то деструктор ничего не удаляет... Он обьект уничтожает...

A>имеем мемори лик.

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

A>хорошо про это описано в Scott Meyers. More Effective C++

Вообще-то у Мейерса описан несколько другой случай. И мораль из этого случая несколько другая...

-----------------------

Что же касается flaws — кажется заметил еще один (удивительно как его проглядели остальные )... у AbstractHandle деструктор-то невиртуальный, хотя класс по своим функциям является абстрактным предком...
____________________
God obviously didn't debug, hasn't done any maintenance, and no documentation can be found. Truly amateur work.
Re: How many flows?
От: MaximE Великобритания  
Дата: 12.06.03 16:47
Оценка:
Здравствуйте, agrilya, Вы писали:

A>Find as many flows as you can in the following code. Please describe each of them in detail.


[]

Ни одной ошибки в коде нет. Код 100% корректен.

Несколько смущают названия классов и спецификаторы доступа, но мы же не знаем что хотел автор.
Re[4]: How many flows?
От: Аноним  
Дата: 12.06.03 16:49
Оценка:
Здравствуйте, Awaken, Вы писали:

A>объект не сконструируется полностью. соответственно не сможет быть удален деструктором. имеем мемори лик.

A>хорошо про это описано в Scott Meyers. More Effective C++

Конструктор не может ничего возвращать вызывающей функции. Исключения — это едиственный и правильный метод сообщить вызывающей функции, что инициализация закончилась неудачно. Никаких мемори ликов в этом случае не будет. Исключение в констркторе -> объект не создан -> память освобождается, деструктор не вызывается потому что нету еще объекта(и уже не будет)
Re: How many flows?
От: Андрей Тарасевич Беларусь  
Дата: 12.06.03 16:54
Оценка:
Здравствуйте, agrilya, Вы писали:

A>Find as many flows as you can in the following code. Please describe each of them in detail.


Во-первых, имелось в виду видимо 'flaws', а не 'flows'.

Во-вторых, как уже правильно заметили, без описания замысла автора кода, общих идей дизайна, роли использованных классов и т.п. ни о каких flaws речи быть не может. Без этого можно судить только о том, является ли код well- или ill-formed. Т.е. если код компилируется стандартным компилятором, то никаких flaws в нем нет.
Best regards,
Андрей Тарасевич
Re[2]: How many flows?
От: Аноним  
Дата: 12.06.03 17:35
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

<...>

Я не думаю, что leak при использовании ConcreteHandle — это правильно.
Но, конечно, мы не знаем, что делают функции MyAPIConnect/MyAPIDisconnect — вполне возможно MyAPIConnect печатает "hello word", а MyAPIDisconnect — форматирует C:. Хех.
Re[5]: How many flows?
От: Awaken Украина  
Дата: 12.06.03 18:21
Оценка:
А>Конструктор не может ничего возвращать вызывающей функции. Исключения — это едиственный и правильный метод сообщить >вызывающей функции, что инициализация закончилась неудачно. Никаких мемори ликов в этом случае не будет. Исключение

я не про данный случай который ничего не делает. представь что в конструкторе создается динамический объект а потом конструктор кидает исключение. этот объект не будет удален деструктором. "откатить" операцию new ты тоже не сможешь

class Unsafe
{
   MyString * ss;
public:
   Unsafe()
   {
       ss = new MyString("ccc");
       throw 1;
   }
   ~Unsafe()
   {
       delete ss; // не выполнится никогда
   }
};


имхо безопаснее не кидаться исключениями а хранить внутри класса булевый флаг который устанавливается конструктором в true или false при успешной/неуспешной инициализации.
соответственно любой последующий метод этого класса проверяет этот флаг и если false возвращает ошибку.
тут надо по ситуации смотреть , если конструктор не создает объектов которые обязательно требуют уничтожения,
то исключения кидать можно
Re[5]: How many flows?
От: Awaken Украина  
Дата: 12.06.03 18:26
Оценка:
A>>имеем мемори лик.
TMH>Не имеем. Так как несмотря на то что обьект не создался, память выделенная под него будет освобождена.

да нет же. может я неясно выразился. в данном коде используется некая функция connect() и disconnect()
предположим connect открывает некий ресурс ОС (хендл) в предположении что disconnect() его освобождает
connect у нас вызвался, конструктор грохнулся, деструктор вызван не будет и "откатить" вызов connect обратно
мы тоже не можем. вероятно будет утечка ресурсов (не памяти)
Re[3]: How many flows?
От: Павел Кузнецов  
Дата: 12.06.03 18:28
Оценка:
Здравствуйте, Вы писали:

> Я не думаю, что leak при использовании ConcreteHandle — это правильно.


А в чем заключается leak?.. Что-то я его в упор не вижу... Этот код вообще безвреден.
ConcreteHandle::connect() и ConcreteHandle::disconnect() при создании/разрушении
объектов типа ConcreteHandle вызваны не будут. Вместо этого будут вызваны
AbstractHandle::connect() и AbstractHandle::disconnect().
Posted via RSDN NNTP Server 1.5 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: How many flows?
От: Аноним  
Дата: 12.06.03 18:31
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

<...>

Оопс, лажа с моей стороны.
Пойду, сделаю с собой что-нибудь, хех.
Re[6]: How many flows?
От: Андрей Тарасевич Беларусь  
Дата: 12.06.03 18:32
Оценка:
Здравствуйте, Awaken, Вы писали:

А>>Конструктор не может ничего возвращать вызывающей функции. Исключения — это едиственный и правильный метод сообщить >вызывающей функции, что инициализация закончилась неудачно. Никаких мемори ликов в этом случае не будет. Исключение


A>я не про данный случай который ничего не делает. представь что в конструкторе создается динамический объект а потом конструктор кидает исключение. этот объект не будет удален деструктором. "откатить" операцию new ты тоже не сможешь


A>
A>class Unsafe
A>{
A>   MyString * ss;
A>public:
A>   Unsafe()
A>   {
A>       ss = new MyString("ccc");
A>       throw 1;
A>   }
A>   ~Unsafe()
A>   {
A>       delete ss; // не выполнится никогда
A>   }
A>};
A>


A>имхо безопаснее не кидаться исключениями а хранить внутри класса булевый флаг который устанавливается конструктором в true или false при успешной/неуспешной инициализации.


Ну так а при чем здесь именно конструктор? Такое может произойти в любой функции: создается динамический объект, потом кидается исключение и ага... Так что из этого следует, что если в некоторой функции создаются динамические объекты, то эта функция не может кидать исключения? Это полная ерунда. Код, создающий динамические объекты, должен быть написан так, чтобы он был безопасным с точки зрения исключений.

В данном случае твой код не удовлетворяет этому требованию из-за того, что ты небезопасным образом создаешь динамический объект. Это твоя ошибка. Ни исключения, ни динамические объекты тут ни в чем не виноваты. Создавай объект безопасным образом — и никаких проблем с исключениями не будет. Это можно сделать разными способами. Можно так:

class Safe
{
   std::auto_ptr<MyString> ss;

public:
   Safe() : ss(new MyString("ccc"))
   { 
     ...
     throw 1; 
     ...
   }
};


А можно так:

class Safe
{
   MyString * ss;

public:
   Safe()
   {
     std::auto_ptr<MyString> lss(new MyString("ccc"));
     ...
     throw 1;
     ...
     ss = lss.release();
   }

   ~Safe()
     { delete ss; }
};
Best regards,
Андрей Тарасевич
Re[6]: How many flows?
От: Аноним  
Дата: 13.06.03 10:23
Оценка:
Здравствуйте, Awaken, Вы писали:

A>я не про данный случай который ничего не делает. представь что в конструкторе создается динамический объект а потом конструктор кидает исключение. этот объект не будет удален деструктором. "откатить" операцию new ты тоже не сможешь


A>
A>class Unsafe
A>{
A>   MyString * ss;
A>public:
A>   Unsafe()
A>   {
A>       ss = new MyString("ccc");
A>       throw 1;
A>   }
A>   ~Unsafe()
A>   {
A>       delete ss; // не выполнится никогда
A>   }
A>};
A>


A>имхо безопаснее не кидаться исключениями а хранить внутри класса булевый флаг который устанавливается конструктором в true или false при успешной/неуспешной инициализации.

A>соответственно любой последующий метод этого класса проверяет этот флаг и если false возвращает ошибку.
A>тут надо по ситуации смотреть , если конструктор не создает объектов которые обязательно требуют уничтожения,
A>то исключения кидать можно

Да, в приведенном коде delelte ss не выполниться никогда. Но это просто пример небезопастного к исключениям кода. Так делать не надо. Если конструкотор помимо захвата каких либо ресурсов делает еще что-то что может кинуться исключением, то захват и освобождение ресурсов надо выделять в отдельный класс и инициализировать его до момента возможного возбуждения исключения. В приведенном тобой случае изобретать велосипед не надо — ss должен быть не MyString* , а std::auto_ptr<MyString>.

Safe() : ss(new MyString("ccc"))
{
     throw 1;
}


После throw 1 деструктор ss удалит все что надо удалить.
Re[6]: How many flows?
От: alexkro  
Дата: 15.06.03 08:13
Оценка:
Здравствуйте, Awaken, Вы писали:


A>>>имеем мемори лик.

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

A>да нет же. может я неясно выразился. в данном коде используется некая функция connect() и disconnect()

A>предположим connect открывает некий ресурс ОС (хендл) в предположении что disconnect() его освобождает
A>connect у нас вызвался, конструктор грохнулся, деструктор вызван не будет и "откатить" вызов connect обратно
A>мы тоже не можем. вероятно будет утечка ресурсов (не памяти)

Один момент. connect() вызывается из конструктора базового класса. Поэтому, хотя эта функция и виртуальная, компилятор сгенирирует статические вызов. Т.е. позовется AbstractHandle::connect(), а она пустая! Никакой утечки нет.

Код, конечно, не рабочий .
Re[7]: How many flows?
От: WolfHound  
Дата: 15.06.03 19:34
Оценка:
Здравствуйте, alexkro, Вы писали:

A>Код, конечно, не рабочий .

Но безвредный.
... << RSDN@Home 1.0 beta 6a >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.