2012-06-23 2 views
2

У меня проблема с стилем в моем коде, что я задаюсь вопросом, встретились ли другие. Скажем, у меня есть класс, который либо не имеет конструктора по умолчанию, либо имеет конструктор по умолчанию, который я не хочу вызывать (для определения производительности и стиля). Для примера предположим, что это объект File.Исключить исключение из объявления переменной

Теперь давайте предположим, что у меня есть файл, содержащий список имен файлов, удаляемых ... И я хочу сделать следующее:

File f("foo"); 
for (const string& filenameToDelete : f.Lines()) 
    File(filenameToDelete).Delete(); 

Файл может бросить FileNotFound в конструкторе или в функции удаления , Мой код должен на первый раз удалять файл, но не должен бросать, если файл «foo» не существует (отсутствие файла просто означает, что ничего не нужно удалить).

Я хотел бы написать что-то вроде этого:

try { File f("foo"); } catch (FileNotFound) { return; } 
for (const string& filenameToDelete : f.Lines()) 
    File(filenameToDelete).Delete(); 

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

unique_ptr<File> f; 
try { f.reset(new File("foo")); } catch (FileNotFound) { return; } 
for (const string& filenameToDelete : f->Lines()) 
    File(filenameToDelete).Delete(); 

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

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

struct FileNotFoundToRethrow : public FileNotFound {}; 
try 
{ 
    File f("foo"); 
    try 
    { 
     for (const string& filenameToDelete : f.Lines()) 
      File(filenameToDelete).Delete(); 
    } 
    catch (FileNotFound) 
    { 
     throw FileNotFoundToRethrow(); 
    } 
} 
catch (FileNotFoundToRethrow) { throw; } 
catch (FileNotFound) { return; } 

я нахожу это довольно некрасиво, это трудно понять, что все, что я хочу сделать, это обрабатывать Исправлено исключение FileNotFound в первой строке ... Любой лучший способ?

+0

Почему вы настаиваете на написании 'File (filenameToDelete) .Delete()' в качестве одного оператора? Если вы разделите это на 'File foo (filenameToDelete)' и затем 'foo.Delete()', похоже, что вы сможете делать то, что хотите. – jjlin

+0

Я писал их как одно заявление в основном, чтобы сделать пример как можно короче (чтобы сэкономить время читателю). Я не уверен, что вижу, как разделение линии на две помогло бы в моем случае. – anonymous

+0

_Boost.Optional_ будет работать так же, как 'unique_ptr', за исключением того, что не требуется выделение. –

ответ

1

Я хотел бы сделать это с флагом

bool throwOnNotFound = false; 

try 
{ 
    File f("foo"); 

    throwOnNotFound = true; 

    for (const string& filenameToDelete : f.Lines()) 
     File(filenameToDelete).Delete(); 
} 
catch (FileNotFound) 
{ 
    if (throwOnNotFound) 
     throw; 
} 
+0

Вы правы, что он чище, чем мое определение нового типа исключения! Мне все еще не нравится тот факт, что блок catch находится далеко от линии, для которой мы хотим обработать исключение ... – anonymous

1

Существует, возможно, путь для всех тех, кто чувствует себя особенно умник, extending the lifetime with reference to const. Но есть недостатки. Класс должен иметь нулевой (или по умолчанию) объект, и, ну, ссылка const.

File fooFile() 
{ 
    try { return File("foo"); } catch (FileNotFound) { return File::Default; } 
} 

использовать его:

const File& foo = fooFile(); 

if (foo.IsDefault()) 
    return; 

for (const string& filenameToDelete : f.Lines()) 
     File(filenameToDelete).Delete(); 
Смежные вопросы