Я знаю, что это уродливое и временное решение, но я использую это:
tail -f log / development.log | grep -vE 'актив'
А как насчет использования указателя (или какой-либо его версии RAII)?
VACaptureSource* input = NULL;
try {
input = new VACaptureSource(...);
} catch(...) {
//error handling
}
//And, of course, at the end of the program
delete input;
Локальная переменная привязана к блоку, в котором она выделена (например, Java), но она разрушится, как только блок закончится (в отличие от Java), поэтому вы должны либо делать все, что вы хотите в самом блоке try (что может быть нежелательно, если вы хотите обрабатывать только исключения конструктора), или вам следует выделить объект в другом месте (например, в куче) и использовать указатель в родительском блоке для доступа к нему.
почему вам нужно ссылаться на него вне блока try
?
Вместо
try {
VACaptureSource input = VACaptureSource("image", "/home/cuneyt/workspace/testmedia/face_images/jhumpa_1.jpg");
}
//catch....
//do stuff with input
вы можете переместить все в блок try:
try {
VACaptureSource input = VACaptureSource("image", "/home/cuneyt/workspace/testmedia/face_images/jhumpa_1.jpg");
//do stuff with input
}
//catch....
или вы можете выделить это в отдельную функцию, которая вызывается из блока try:
void doStuff(VACaptureSource& input){
//do stuff with input
}
try {
VACaptureSource input = VACaptureSource("image", "/home/cuneyt/workspace/testmedia/face_images/jhumpa_1.jpg");
doStuff(input);
}
//catch....
Последняя даже дает вам приятное бонус в виде отделения конструкции от использования, который хорошо помещается в модульные тесты, где вместо этого вы можете захотеть, чтобы функция работала с фиктивным объектом.
Могу я просто заметить, что почти любой , но самый тривиальный конструктор может генерировать исключение. Поэтому вы не должны рассматривать исключения как «особые» в каком-то смысле, а вместо этого пишите свой код так, чтобы он работал с ними естественным образом. Это означает использование RAII и других методов, предложенных здесь другими ответами.
Вы можете использовать указатель
VACaptureSource* input;
// Create input data object
try {
input = new VACaptureSource("image", "/home/cuneyt/workspace/testmedia/face_images/jhumpa_1.jpg");
}
catch( invalid_argument& ia ) {
cerr << "FD Error: " << ia.what() << endl;
usage(argv[0]);
}
catch( runtime_error& re ) {
cerr << "FD Error: " << re.what() << endl;
usage(argv[0]);
}
И вам нужно освободить объект, когда вы закончите его использовать
delete input
Я не могу сказать
VACaptureSource input;
в начале программы, поскольку нет конструктора по умолчанию.
Есть веская причина, по которой вы не создали конструктор по умолчанию: а именно, что VACaptureSource
имеет смысл только тогда, когда он связан с файлом. Так что не создавайте конструктор по умолчанию. Вместо этого просто распознайте, что областью действия объекта VACaptureSource
является блок try
, и используйте его внутри.
Как насчет добавления конструктора по умолчанию, который оставляет объект в специальном ненастроенном состоянии? Затем используйте функцию create () для его создания.
Затем вы можете сделать:
VACaptureSource input;
try
{
input.create("image", "...");
}
catch(...)
{
...
}
В зависимости от ситуации это может быть лучше, чем возиться с указателями. Хотя тогда вы также должны проверить, действительно ли был вызван create (), прежде чем что-то делать ...
На самом деле я не вижу здесь никаких проблем:
Я бы обновил пару вещей:
Так что я бы сделал это (для ясности).
VACaptureSource::VACaptureSource( std::string const& inputType,
std::string const& inputLocation )
:type(inputType)
,location(inputLocation)
{
// Other Code that throws.
}
void playWithCode()
{
// Get input information from user.
VACaptureSource input("image", "/home/cuneyt/workspace/testmedia/face_images/jhumpa_1.jpg");
// use the input object.
// Do not need to play with pointers here.
}
int main()
{
try
{
playWithCode();
}
catch( invalid_argument const& ia )
{ cerr << "FD Error: " << ia.what() << endl;
usage(argv[0]);
}
catch( runtime_error const& re )
{ cerr << "FD Error: " << re.what() << endl;
usage(argv[0]);
}
}
Простой. Не создавайте исключений в конструкторе. Вы не только должны заключить конструктор в блок try, но и не сможете очень хорошо обрабатывать память, если поймаете исключение (вызываете ли вы деструктор? Какая часть памяти класса должна быть удалена? )
UPDATE0 : Хотя я не уверен, является ли управление памятью проблемой, если вы используете экземпляр.
UPDATE1 : Хммм, может быть, я думаю об исключениях в деструкторы .
int
main2(int argc, char* argv[])
{
MyClass class;
class.doSomething();
}
int
main(int argc, char* argv[])
{
int result = 0;
try {
main2(argc, argv);
} catch (std::exception& se) {
// oh noes!
result = 1;
}
return result;
}