Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Конструктор в стиле ООП или нет? 
:(
    Опции темы
EvilsInterrupt
Дата 19.6.2010, 20:38 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



Написал констуктор классу:
Код

cDriver::cDriver(std::string filename)
: m_hSCManager( OpenSCManagerA(NULL,NULL,SC_MANAGER_CREATE_SERVICE) ),
  m_hService(NULL),
  m_Filename(filename), m_SrvName(""), m_Displayname("")
{
  const char * errtxt;
  bool   error = false;
  size_t begin_ = 0;
  size_t end_   = 0;

  do 
  {
    if(!m_hSCManager) {
      error  = true;
      errtxt = "Open Service control manager failed";
      break;
    }

    if(filename.length()<=1) {
      error  = true;
      errtxt =  "Filename isn't specified";
      break;
    }

    /* Detect incomplete filename: example <application.exe "cthulhu.sys"> */
    if(std::find(filename.begin(), filename.end(),'\\')==filename.end())
    {
      char   FullName[MAX_PATH] = {0};
      char * pPartFile = NULL;

      if( !GetFullPathNameA(filename.c_str(),sizeof(FullName),FullName,&pPartFile) )
      {
        error  = true;
        errtxt = "Get full path failed";
        break;
      }

      m_Filename = FullName;
    }

    begin_ = m_Filename.find_last_of('\\') + 1;
    end_   = m_Filename.find_last_of('.');
    if(-1 == end_)
      end_ = m_Filename.length();

    const int MIN_DRVFILE_NAME = 4;
    if(!begin_ || begin_ >= m_Filename.length() - MIN_DRVFILE_NAME) {
      error  = true;
      errtxt = "Filename not stated";
      break;
    }

  } while (false);

  if(error) {
    CloseServiceHandle(m_hSCManager);
    throw(driver_error(errtxt));
  }

  m_SrvName     = m_Filename.substr(begin_,end_ - begin_);
  m_Displayname = m_SrvName + " driver";
}


Хотелось бы узнать, что думает матерый С++ - гуру ? ;) Т.е. с высоты нескольких лет использования ++.

Отмечу, что тут do - whihe нужен для того чтоб свести обработку и корректный откат в одно место! ;)
PM MAIL WWW ICQ Jabber   Вверх
Abyx
Дата 19.6.2010, 20:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 601
Регистрация: 3.11.2009

Репутация: 1
Всего: 10



Это God-Constructor, разновидность God-Function
PM MAIL   Вверх
ISergeyN
Дата 19.6.2010, 20:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 11.10.2008
Где: Україна

Репутация: нет
Всего: 2



Код

cDriver::cDriver(const std::string &filename)

PM MAIL Skype   Вверх
EvilsInterrupt
Дата 19.6.2010, 21:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



ISergeyN, Сделано было специально, потому что думаю что если передам char *, то ахтунг ) Может и ошибаюсь,

Пример, будет ли это работать с добавлением "&"  ? :

cDriver drvr("Cthulhu.sys");

или надо будет:

cDriver drvr(std::string("Cthulhu.sys") );

?

Более, того. Вы предлагаете ссылку, а значит в конструкторе нужно ссылаться на конкретный объект! А что если перечислю список дров для тестировани из ини-файла и удалю их потом ,т.е. все будет в динамике, то на что ссылаться то?

Потому мне кажется лучше по значению, а не ссылке )
PM MAIL WWW ICQ Jabber   Вверх
ISergeyN
Дата 19.6.2010, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 59
Регистрация: 11.10.2008
Где: Україна

Репутация: нет
Всего: 2



Код

#include <iostream>
#include <string>

void func(const std::string &rhs){
    std::cout << rhs << std::endl;
}
 
int main()
{
    func("Hello");
    return 0;
}


http://codepad.org/tPCL89kP
PM MAIL Skype   Вверх
bsa
Дата 19.6.2010, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



EvilsInterrupt, стандартный способ передачи СЛОЖНЫХ объектов в качестве параметра - по константной ссылке. Твои страхи беспочвенны. у std::string конструктор от const char* не explicit, поэтому передавать строковые литералы можно.
PM   Вверх
borisbn
Дата 19.6.2010, 22:17 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Не советую выбрасывать исключения из конструктора - дурной тон


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
EvilsInterrupt
Дата 19.6.2010, 22:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



borisbn, Почему? То что не производительно по скорости выполнения согласен,  но почему дурной тон? Если объект был должен создан,  а он не создался, то что? Это разве просто ошибка? Нет! Это исключительная ситуация!
PM MAIL WWW ICQ Jabber   Вверх
borisbn
Дата 20.6.2010, 06:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



EvilsInterrupt, под руками нет отладчика (к сожалению не помню) чтобы проверить, вызовется ли в этом случае деструктор. А если и вызовется, то как ему удалять наполовину созданный объект. IMHO в ситуации, когда может произойти исключительная ситуация создать отдельную функцию инициализации.
Хотя, ладно, согласен, что и так можно. Просто у нас на фирме это - дурной тон (мы используем Qt, и потихоньку начинаем перенимать их стиль)


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
azesmcar
Дата 20.6.2010, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(borisbn @  19.6.2010,  22:17 Найти цитируемый пост)
Не советую выбрасывать исключения из конструктора - дурной тон 

мало того - опасно!
Код

#include <iostream>
#include <stdexcept>

struct A
{
    void foo()
    {
        throw std::runtime_error("error 1");
    }
    ~A()
    {
        throw std::runtime_error("error 2");
    }
};

int main()
{
    try
    {
        A t;
        t.foo();
    } catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }
}

и еще пример
Код

#include <iostream>
#include <stdexcept>

struct A
{
    ~A()
    {
        throw std::runtime_error("error 2");
    }
};

int main()
{
    try
    {
        A arr[10];
    }
    catch (std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }
}

тут конечно можно использовать std::uncaught_exception(), но зачем это нужно?
Код

~A()
{
    if (!std::uncaught_exception())
        throw std::runtime_error("error 2");
}


Это сообщение отредактировал(а) azesmcar - 20.6.2010, 09:55
PM   Вверх
cutwater
Дата 20.6.2010, 09:56 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 592
Регистрация: 24.6.2008

Репутация: 1
Всего: 10



эм... мне кажется или кто-то путает конструктор с деструктором?

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


--------------------
user posted image
PM MAIL   Вверх
azesmcar
Дата 20.6.2010, 09:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(cutwater @  20.6.2010,  09:56 Найти цитируемый пост)
эм... мне кажется или кто-то путает конструктор с деструктором?

черт, написано конструктор, прочитал деструктор smile 

Цитата(cutwater @  20.6.2010,  09:56 Найти цитируемый пост)
ибо в деструкторе да, исключения бросать нельзя.

ну так мой пример про деструкторы smile

Добавлено через 2 минуты и 12 секунд
неправильно прочитал, исправляюсь
Цитата(borisbn @  19.6.2010,  22:17 Найти цитируемый пост)
Не советую выбрасывать исключения из конструктора - дурной тон 

ничего дурного в этом нет. smile 
PM   Вверх
EvilsInterrupt
Дата 20.6.2010, 10:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



>>Это God-Constructor, разновидность God-Function

не совсем понял, что вы хотели сказать? ;) Намек на  то что мне  нужно поискать эти термины и после прочтения пойму, что мой конструктор подходит под то что пишут опытные С++-программеры?

>>а в конструкторе это единственно верный способ сообщить об ошибке.
это не только единственный, это лучше не придумаешь! Нахрена скажите человеку идти в магазин за хлебом, если он забыл дома кошелек? Если в мире людей еще можно  надеяться, что кто-то пожалеет или даст в долг, то в мире программ надеяться на что-то никак нельзя! Если от чего-то зависит нарушение достижения основной цели программы, то это "чего-то" исключительная и мало того экстренная ситуация. Ошибку можно не проверить, а вот исключение оставить обработанным никак нельзя!

>> под руками нет отладчика (к сожалению не помню) чтобы проверить, вызовется ли в этом случае деструктор. А если и вызовется, то как ему удалять наполовину созданный объект.
Простите но  бред! Объект или создается или не создается и объект считается созданным, только тогда,  когда отработала не только секция инициализация конструктора, т.е. после двоеточия, но и само тело! 1) Деструктор будет вызван исключительно только у созданного объекта и никак иначе! 2) Для внутренних объектов деструктор вызывается не только,  когда удаляется сам объект содержащий, но также и тогда, когда не завершилось тело конструктора,к примеру бросили исключение в тело и после обработки его, решено удалить, тогда произойдет откат создания внутренних, за исключением действий по выделению ресурсов в теле конструктора 3) Для этого нужно все что выделил удалить самому!

>>cDriver::cDriver(const std::string &filename)
учту спасибо!!!
Но к вам вопрос. Что если я хочу в методе вернуть std::string, как лучше это осуществить? По значению, по указателю или ссылке на созданный внутри спомощью new ?

Это сообщение отредактировал(а) EvilsInterrupt - 20.6.2010, 11:13
PM MAIL WWW ICQ Jabber   Вверх
borisbn
Дата 20.6.2010, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Код

#include <iostream.h>
#include <stdio.h>

class FileOpener
{
public:
    FileOpener()
        : m_file( 0 )
    {
        std::cout<< "FileOpener::FileOpener()" << std::endl;
        m_file = fopen( "some_file.txt", "wt" );
        if ( m_file )
        {
            fprintf( m_file, "some text\n" );
        }
    }
    ~FileOpener()
    {
        std::cout<< "FileOpener::~FileOpener()" << std::endl;
        if ( m_file )
        {
            fclose( m_file );
        }
    }
private:
    FILE * m_file;
};

class A
{
public:
    A()
        : m_fileOpener( 0 )
    {
        std::cout << "A::A() entry" << std::endl;
        m_fileOpener = new FileOpener();
        std::cout << "A::A() before throw" << std::endl;
        throw( 1 );
    }
    ~A()
    {
        std::cout << "A::~A()" << std::endl;
        delete m_fileOpener;
    }
private:
    FileOpener * m_fileOpener;
};

int main()
{
    std::cout << "entry" << std::endl;
    try
    { 
        A a;
    }
    catch( ... )
    {
        std::cout << "catched" << std::endl;
    }
    std::cout << "exit" << std::endl;
}


Output:
Цитата

entry
A::A() entry
FileOpener::FileOpener()
A::A() before throw
catched
exit


http://codepad.org/knrUAMBO

Это сообщение отредактировал(а) borisbn - 20.6.2010, 10:58


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
EvilsInterrupt
Дата 20.6.2010, 11:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



borisbn, С какой целью вы привели свой код? ;) Если просто показать, что ничего такого в бросании ислкючений в конструкторе, то по-моему уже два поста, + мой сегодняшний говорят о том что :
Цитата

ничего дурного в этом нет. 

PM MAIL WWW ICQ Jabber   Вверх
borisbn
Дата 20.6.2010, 11:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



EvilsInterrupt, с целью показать, что файл, открытый в конструкторе дочернего объекта FileOpener, не закроется, если выбросить исключение из A:A().


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
EvilsInterrupt
Дата 20.6.2010, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



>>EvilsInterrupt, с целью показать, что файл, открытый в конструкторе дочернего объекта FileOpener, не закроется, если выбросить исключение из A:A().
Дело в том что то что сделано до работы тела вашего конструктора, откатится само! ;) А все что сделано в вашем теле, вами в ручную так сказать, то в случае ошибки перед выбрасыванием исключения , вы должны откатить сами!!!
Об этом я и писал:
Цитата

2) Для внутренних объектов деструктор вызывается не только,  когда удаляется сам объект содержащий, но также и тогда, когда не завершилось тело конструктора,к примеру бросили исключение в тело и после обработки его, решено удалить, тогда произойдет откат создания внутренних, за исключением действий по выделению ресурсов в теле конструктора 3) Для этого нужно все что выделил удалить самому!

и:
Цитата

Отмечу, что тут do - whihe нужен для того чтоб свести обработку и корректный откат в одно место! ;)

PM MAIL WWW ICQ Jabber   Вверх
borisbn
Дата 20.6.2010, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



EvilsInterrupt, OK, судя по всему мы не прийдём к общему мнению, и каждый останется при своём. Мне кажется, что действия по удалению/очищению/откату следует делать в деструкторе, а не в конструкторе. Заметьте, что я не говорил, что нельзя выбрасывать исключения из конструктора, я лишь говорил, что это - дурной тон, причём с добавлением:
Цитата(borisbn @  20.6.2010,  06:48 Найти цитируемый пост)
Хотя, ладно, согласен, что и так можно. Просто у нас на фирме это - дурной тон (мы используем Qt, и потихоньку начинаем перенимать их стиль)

Предлагаю за сим hollywar закончить smile

Это сообщение отредактировал(а) borisbn - 20.6.2010, 12:32


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
borisbn
Дата 20.6.2010, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



P.S. Sorry за  smile 
ISergeyN, а как ты в своём первом посте выделил фон символа &


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
EvilsInterrupt
Дата 20.6.2010, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



borisbn, Если излишне к Вам.. прошу простить. Просто люблю аргументацию, от которой не отвертеться ;) Из всего приведенного мною выше на ваши ответы, у меня только один ответ : Как вы поступаете , если выделены\получены\открыты ресурсы в теле конструктора , а под конец скажем из 5 успешных действий у вас вдруг отработали только 3, что тогда ?
PM MAIL WWW ICQ Jabber   Вверх
borisbn
Дата 20.6.2010, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(EvilsInterrupt @  20.6.2010,  12:53 Найти цитируемый пост)
Как вы поступаете , если выделены\получены\открыты ресурсы в теле конструктора , а под конец скажем из 5 успешных действий у вас вдруг отработали только 3, что тогда ?

Удаляю/отдаю/закрываю только те, для которых всё было успешно выделено.
Код
C::C() : p( 0 ), manager( 0 ), resource( 0 ) {  
    manager = getManager();
    if ( manager )
        resource = getResoure( manager );
    p = new P();
}
C::~C(){  
    delete p;
    if ( manager )
    {
        if ( resource )
            freeResource( manager, resource );
        freeManager( manager );
    }
}


Цитата(EvilsInterrupt @  20.6.2010,  12:53 Найти цитируемый пост)
Просто люблю аргументацию, от которой не отвертеться ;) 

Подписываюсь, но в случае, когда под аргументами есть неоспоримые доказательства. Согласен ? smile

Это сообщение отредактировал(а) borisbn - 20.6.2010, 13:40


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
mes
Дата 20.6.2010, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



EvilsInterrupt, почитайте про RAII



--------------------
PM MAIL WWW   Вверх
EvilsInterrupt
Дата 20.6.2010, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



>> EvilsInterrupt, почитайте про RAII
А это :
Код

cDriver::cDriver(std::string filename)
: m_hSCManager( OpenSCManagerA(NULL,NULL,SC_MANAGER_CREATE_SERVICE) ),
....
    if(!m_hSCManager) {
      error  = true;
      errtxt = "Open Service control manager failed";
      break;
    }
....
  if(error) {
    CloseServiceHandle(m_hSCManager);
    throw(driver_error(errtxt));
  }


не попадает под RAII ? Захват ресурса в точке инициализации, потом проверка ;) или чтото не так?
PM MAIL WWW ICQ Jabber   Вверх
mes
Дата 20.6.2010, 14:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(EvilsInterrupt @  20.6.2010,  13:01 Найти цитируемый пост)
не попадает под RAII ?

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

Код

// не RAII
int *p = new int[10];
delete p; 

// RAII
std::auto_ptr<int>  p ( new int[10] );


Добавлено через 1 минуту и 18 секунд
Цитата

Получение ресурса есть инициализация (англ. Resource Acquisition Is Initialization (RAII)) — шаблон проектирования объектно-ориентированного программирования, смысл которого заключается в том, что получение некоторого ресурса совмещается с инициализацией, а освобождение — с уничтожением объекта.


http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%...%86%D0%B8%D1%8F


--------------------
PM MAIL WWW   Вверх
EvilsInterrupt
Дата 20.6.2010, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



Получение?
Вот:
Цитата

cDriver::cDriver(std::string filename)
: m_hSCManager( OpenSCManagerA(NULL,NULL,SC_MANAGER_CREATE_SERVICE) ),

совмещено с инциализацией!

>>а освобождение — с уничтожением объекта.
Деструктор не привел, тема про конструктор!!! То что не  приведено еще не означает, что не написано совсем,  но  спасибо за напоминание ;)

Это RAII ! т.к. получение в секции инициализации. Только одно многие забывают, что деструктор не будет вызван  , если тело вашего конструктора не отработало полностью!!! Таким образом бросая исключение вы лишаете себя работы деструктора и это означает, что именно вы берете на себя отвественность за освобождение ресурсов в случае некорректного создания объекта. Об этом-то я и писал выше в посте



PM MAIL WWW ICQ Jabber   Вверх
maxim1000
Дата 20.6.2010, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



при бросании исключении в конструкторе деструктор для этого объекта действительно не будет вызван, но вот деструкторы членов объекта - будут

в данном случае, если бы m_hSCManager имел деструктор, в котором был вызов CloseServiceHandle, не пришлось бы вручную его вызывать ни в деструкторе, ни в обработке ошибки в конструкторе


--------------------
qqq
PM WWW   Вверх
EvilsInterrupt
Дата 20.6.2010, 15:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



>>но вот деструкторы членов объекта - будут
Об этом я и писал, вот:
Цитата

2) Для внутренних объектов деструктор вызывается не только,  когда удаляется сам объект содержащий, но также и тогда, когда не завершилось тело конструктора,к примеру бросили исключение в тело и после обработки его, решено удалить, тогда произойдет откат создания внутренних, за исключением действий по выделению ресурсов в теле конструктора 3) Для этого нужно все что выделил удалить самому!


>>в данном случае, если бы m_hSCManager имел деструктор, в котором был вызов CloseServiceHandle, не пришлось бы вручную его вызывать ни в деструкторе, ни в обработке ошибки в конструкторе
Да, согласен! Но в данной ситуации это не объект класса, а хэндл полученный в результате вызова Win32(Wow64) функции! Поэтому-то мне и надо откатываться самому вызовом CloseServicHandle, т.к. за меня никто этого не сделает !!!

PM MAIL WWW ICQ Jabber   Вверх
mes
Дата 20.6.2010, 15:17 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(EvilsInterrupt @  20.6.2010,  13:33 Найти цитируемый пост)
Это RAII ! т.к. получение в секции инициализации. Только одно многие забывают, что деструктор не будет вызван 

не туда смотрите.. речь не об объекте, конструктор которого Вы привели..в данном случае он нам не интересен.. Речь  о "технологии " примененной внутри конструктора .. При проектированнии в стиле RAII не пришлось бы так нагружать логику конструктора.. 
smile

Добавлено через 2 минуты и 2 секунды
Цитата(EvilsInterrupt @  20.6.2010,  14:07 Найти цитируемый пост)
Но в данной ситуации это не объект класса, а хэндл полученный в результате вызова Win32(Wow64) функции!

Так вместо того чтоб в каждом месте использовать сырой хэндл, легче в одном месте написать обертку - и сразу разгрузиться все остальное smile


--------------------
PM MAIL WWW   Вверх
bsa
Дата 20.6.2010, 15:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



EvilsInterrupt, это делается так:
Код
clas cDriver {
...
private:
   struct CSMHandle;
...
};

...

struct cDriver::CSMHandle
{
    CSMHandle() {
        handle_ = OpenSCManagerA(NULL,NULL,SC_MANAGER_CREATE_SERVICE);
        if (!handle_)
           throw driver_error("Open Service control manager failed");
    }
    ~CSMHandle() {
       CloseServicHandle(handle_);
    }
    SC_HANDLE handle() { return handle_; }
private:
    SC_HANDLE handle_;
    //объекты нельзя копировать (у этих методов нет тела - это правильно)
    CSMHandle(const CSMHandle&);
    CSMHandle& operator=(const CSMHandle&);
};
Таким образом, если у тебя дойдет до конструктора объекта, содержащего объект класса CSMHandle, то значит handle валиден. В противном случае будет кинуто исключение.
PM   Вверх
kemiisto
Дата 20.6.2010, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дикий Кот. =^.^=
****
Награды: 1



Профиль
Группа: Участник Клуба
Сообщений: 3292
Регистрация: 29.7.2007

Репутация: 2
Всего: 160



Цитата(EvilsInterrupt @  19.6.2010,  21:38 Найти цитируемый пост)
Отмечу, что тут do - whihe нужен для того чтоб свести обработку и корректный откат в одно место! ;) 

Ни Макконнелла, случайно, начитались?




--------------------
PM MAIL WWW GTalk Jabber   Вверх
EvilsInterrupt
Дата 20.6.2010, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



>>Ни Макконнелла, случайно, начитались?
Нет, надоело при обработке очередной ошибке делать откат уже успешно завершенных действия, а по сути тело-движения по зачистке повторяются. Поэтому стал сводить в одно место. )

>>Таким образом, если у тебя дойдет до конструктора объекта, содержащего объект класса CSMHandle, то значит handle валиден. В противном случае будет кинуто исключение.
Согласен будет!

Но! Для этого вам придется писать класс-обертку, для получения валидного хэндла. А по сути этот враппер будет использоваться исключительно один раз, классом cDriver! Если бы два и более класса использовали враппер,то целесообразность вижу, т.к. повторное использование. 

PM MAIL WWW ICQ Jabber   Вверх
mes
Дата 20.6.2010, 16:39 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(EvilsInterrupt @  20.6.2010,  15:33 Найти цитируемый пост)
! Если бы два и более класса использовали враппер,то целесообразность вижу, т.к. повторное использование. 

целесообразность в образе мысли.. bsa привел вариант исполнения.. вполне возможно это реализовать и по другому.. суть в том, что Вы должны в уме сначале спроектировать взаимоотношения, а потом уже выразить на ЯП.. По примеру констуктора видно, что в глубину взаимотношений вы не заглянули, а решали сразу поверхностными средствами.. 
smile

P.S. пытался показать в чем у Вас ошибка проектирования..

Добавлено через 5 минут и 28 секунд
Цитата(EvilsInterrupt @  20.6.2010,  15:33 Найти цитируемый пост)
исключительно один раз, 

А Вы попробуйте написать так и сравните с тем, что было у Вас... Отсутствие всей этой надуманности с while уже стоит написания обертки..



--------------------
PM MAIL WWW   Вверх
EvilsInterrupt
Дата 20.6.2010, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



mes, В приведенной вами ссылке на RAII. Смотрю код и играю в игру "найди отличия" ?:

Код

private:
    std::FILE* m_file_handle ;


у меня это:
Код

class cDriver {
  SC_HANDLE   m_hSCManager;


у него:
Код

    file( const char* filename ) : m_file_handle(std::fopen(filename, "w+")) 
    {


у меня:
Код

cDriver::cDriver(std::string filename)
: m_hSCManager( OpenSCManagerA(NULL,NULL,SC_MANAGER_CREATE_SERVICE) ),


у него:
Код

    {
        if( !m_file_handle )
            throw std::runtime_error("file open failure") ;


у меня:
Код

    if(!m_hSCManager) {
      error  = true;
      errtxt = "Open Service control manager failed";
      break;
    }
/* которая после break приводит к коду по генарации исключения, т.е. тоже как и  у него ;) */


Что, не так?

>>Отсутствие всей этой надуманности с while уже стоит написания обертки..
Даже если убрать обработку ошибки OpenSCManagerA в класс обертку все равно придется :
I.  Либо Iбросать три раза исключения: 1) имя файла не задано 2) не вернулось полное имя файла 3) невыделилось имя файла без расширение. 
II. Либо все свести к do - while и киданию исключения в одном месте

Мне почему-то куда привычней второй вариант чем размазывать по коду генерацию исключений ;)

>>P.S. пытался показать в чем у Вас ошибка проектирования..
Стараюь перенять ваш опыт! ;) Греки тоже вон спорили. спорили и как у них здорово наука вперед шагнула! ;)

Это сообщение отредактировал(а) EvilsInterrupt - 20.6.2010, 17:02
PM MAIL WWW ICQ Jabber   Вверх
mes
Дата 20.6.2010, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(EvilsInterrupt @  20.6.2010,  15:59 Найти цитируемый пост)
у меня:
у него:


"у него" не было ресурсов за которыми нужно следить вручную
smile

Добавлено через 3 минуты и 56 секунд
Цитата(EvilsInterrupt @  20.6.2010,  15:59 Найти цитируемый пост)
  Либо Iбросать три раза исключения:

это не суть важно.. можно как один , так и несколько..зависит от видения программиста ..
smile

Добавлено через 5 минут и 1 секунду
в общем Вам в конструкторе нужно убрать все то, что "притянуто туда за уши" smile



--------------------
PM MAIL WWW   Вверх
EvilsInterrupt
Дата 20.6.2010, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



mes, все бы хорошо, если бы это один хэндл, то я бы возможно  и последовал решению который вы указываете, к примеру заюзав код BSA. Но в этом же классе используется и другой хэндл от созданного\открытого сервиса, которому нужен валидный хэндл от OpenSCManager'a полученный в cSChandle и если его тоже делать через этот RAII , то потребуется указать хэндл от CSChandle , который указан в качестве приватного. А мы знаем, что компилятор вправе строить код по своему усмотрению,следовательно нет никакого гарантии, что cSChandle создастся быстрее чем класс-обертка вокруг открытия\создания сервиса.

если же хэндлы лежат в сыром виде, то это куда удобнее, пока, для меня ;)

ЗЫ:
Это кажется уже на другую тему тянет )
PM MAIL WWW ICQ Jabber   Вверх
mes
Дата 20.6.2010, 19:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(EvilsInterrupt @  20.6.2010,  17:01 Найти цитируемый пост)
то потребуется указать хэндл от CSChandle , который указан в качестве приватного.

не пойму при чем тут приватный ?..

Цитата(EvilsInterrupt @  20.6.2010,  17:01 Найти цитируемый пост)
А мы знаем, что компилятор вправе строить код по своему усмотрению,следовательно нет никакого гарантии, что cSChandle создастся быстрее чем класс-обертка вокруг открытия\создания сервиса.


Не знаю каких "мы" Вы имели ввиду, но мы знаем, что порядок создания членов класса регламентирован, также как и порядок их удаления..
smile

Добавлено через 3 минуты и 34 секунды
Цитата(EvilsInterrupt @  20.6.2010,  17:01 Найти цитируемый пост)
если же хэндлы лежат в сыром виде, то это куда удобнее, пока, для меня ;)

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



--------------------
PM MAIL WWW   Вверх
EvilsInterrupt
Дата 20.6.2010, 19:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



>>Не знаю каких "мы" Вы имели ввиду, но мы знаем, что порядок создания членов класса регламентирован, также как и порядок их удаления..

я имею ввиду:

Код

class cClass1 {
 cResource1 m_Res1;
 cResource2 m_Res2;
public:
}


В этом случае мы не можем четко говорить о том что создание m_Res1 произойдет первым, а m_Res2 вторым! Поэтому при ситуации, когда класс cClass1 нуждается в открытом класс m_Res2 , а тот в свою очередь нуждается в отрытом m_Res1, мы получим багу ! ;) Вот именно такая у меня  сейчас ситуация.
PM MAIL WWW ICQ Jabber   Вверх
mes
Дата 20.6.2010, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(EvilsInterrupt @  20.6.2010,  18:36 Найти цитируемый пост)
В этом случае мы не можем четко говорить о том что создание m_Res1 произойдет первым, а m_Res2 вторым!


Цитата("12.6.2/5")

Initialization shall proceed in the following order:
...
    * Then, nonstatic data members shall be initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers). 
...


smile



--------------------
PM MAIL WWW   Вверх
mes
Дата 20.6.2010, 20:40 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(mes @  20.6.2010,  18:30 Найти цитируемый пост)
не нам же за Вас напрягаться 

ну ладно "уговорили"..  гляну еще раз код.. и прокомментирую

Код

cDriver::cDriver(std::string filename)  // порядок
: m_hSCManager( OpenSCManagerA(NULL,NULL,SC_MANAGER_CREATE_SERVICE) ), // пойдет
  m_hService(NULL),  // пусть пока будет
  m_Filename(filename), m_SrvName(""), m_Displayname("") // ну тут вроде ничего страшного
{
  const char * errtxt;  //  это режет глаз
  error = false;          // и это тоже
  size_t begin_ = 0;  // а это вообще здесь к чему ?
  size_t end_   = 0;  // вместе с этим

  do                   // а разве это самый удобный варинат ?
  {
    if(!m_hSCManager) {
      error  = true;
      errtxt = "Open Service control manager failed"; // а почем не вызвать функцию throw_err ("") ?
      break;
    }
 
/* А это закомментим так вообще не относится к конструктору и должно быть выделено в отдельную функцию

    if(filename.length()<=1) { 
      error  = true;
      errtxt =  "Filename isn't specified";
      break;
    }
   
    if(std::find(filename.begin(), filename.end(),'\\')==filename.end())
    {
      char   FullName[MAX_PATH] = {0};
      char * pPartFile = NULL;
      if( !GetFullPathNameA(filename.c_str(),sizeof(FullName),FullName,&pPartFile) )
      {
        error  = true;
        errtxt = "Get full path failed";
        break;
      }
      m_Filename = FullName;
    }
    begin_ = m_Filename.find_last_of('\\') + 1;
    end_   = m_Filename.find_last_of('.');
    if(-1 == end_)
      end_ = m_Filename.length();
    const int MIN_DRVFILE_NAME = 4;
    if(!begin_ || begin_ >= m_Filename.length() - MIN_DRVFILE_NAME) {
      error  = true;
      errtxt = "Filename not stated";
      break;
    }
*/ 
  } while (false);
 
  if(error) {
    CloseServiceHandle(m_hSCManager);
    throw(driver_error(errtxt));
  }
  m_SrvName     = m_Filename.substr(begin_,end_ - begin_); // если уж делали через while, то чего
  m_Displayname = m_SrvName + " driver"; // оставили этот кусок фрагмента снаружи _?!
}


дальнейшие советы будут, после того как представите исправленный код 
smile


--------------------
PM MAIL WWW   Вверх
EvilsInterrupt
Дата 22.6.2010, 19:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



Спрошу еще один вопрос, что лучше:
Код

    if(filename.length()<=1) { 


или:
Код

    if(filename.empty()) { 


?
PM MAIL WWW ICQ Jabber   Вверх
mes
Дата 22.6.2010, 20:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



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

Добавлено через 1 минуту и 3 секунды
P.S. только  "<=1" и "empty()"  не одно и то же.. 


--------------------
PM MAIL WWW   Вверх
EvilsInterrupt
Дата 22.6.2010, 20:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Executables research
***


Профиль
Группа: Завсегдатай
Сообщений: 1019
Регистрация: 14.7.2007
Где: Железнодорожный, МО, Россия

Репутация: 2
Всего: 9



>>P.S. только  "<=1" и "empty()"  не одно и то же.. 
оно-то понятно, если в общем случае ))) Но в данном случае одно и тоже, т.к врядли кто будет создавать имя файла из одного символа! ;) 

ЗЫ:
У меня полностью поменялся дизайн библиотеки ))) Особенно после сегодняшних советов BSA в аське )))
PM MAIL WWW ICQ Jabber   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1936 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.