0

So I've got a program with two exception. In both cases, I'd like to throw a string that can be caught in the main function and used in an error message. However, from what I know about them

    try {
     ...
    } catch(string msg) {
     cerr << "..." << msg << "..." << endl;
    } catch (string msg2) {
     cerr << "..." << msg2 << "..." << endl;
    }

isn't allowed. Is there any way I could do the above or something like it? Thanks

The_Questioner
  • 240
  • 2
  • 7
  • 17
  • 3
    What do you expect that to do? What is the use case? – Amit Feb 21 '16 at 20:59
  • I'm sorry, but I don't know what a use case is. What I'm trying to do is, my program can run into two big errors depending on user input. In both cases, I have a different message to print out. Therefore, I'd like each exception to catch a different message. Is there a way I can id the two string exceptions? – The_Questioner Feb 21 '16 at 21:01
  • 1
    Are you familiar with `if`-statements? – LogicStuff Feb 21 '16 at 21:03
  • Is there a valid reason for which you can't throw an exception and set correctly its *what* argument instead of throwing a string? – skypjack Feb 21 '16 at 21:05
  • What do you mean by its "what argument"? – The_Questioner Feb 21 '16 at 21:07
  • 2
    Throwing something that doesn't inherit from `std::exception` is pretty unfriendly. If you define two different classes that do so inherit then you can easily catch them - either one catch for both or separate catches for each, as appropriate. – Alan Stokes Feb 21 '16 at 21:07
  • Example of deriving exceptions and providing custom `what` strings at throw: http://coliru.stacked-crooked.com/a/5bc27c8dba5b3e34 – Revolver_Ocelot Feb 21 '16 at 21:10

3 Answers3

6

I see two use cases:

1. You want two distinct types of errors.

Add exception classes derived from std::exception

class MyException1 : public std::exception
{
  std::string message;
public:
  MyException1(std::string const &what_arg) : message(what_arg) {}
  MyException1(char const * what_arg) : message(what_arg) {}
  const char* what() const { return message.c_str(); }
};

class MyException2 : public std::exception
{
  std::string message;
public:
  MyException2(std::string const &what_arg) : message(what_arg) {}
  MyException2(char const * what_arg) : message(what_arg) {}
  const char* what() const { return message.c_str(); }
};

and catch those:

try
{

  int a = 5;

  // do stuff

  if (a == 7)
  {
    throw MyException1("Error 1 occured in  because a == 7.");
  }
  else if (a == 5)
  {
    throw MyException1("Error 1 occured because a == 5.");
  }

  // do more stuff

  if (a == 22)
  {
    throw MyException2("Error 2 occured in  because a == 22.");
  }
  else if (a == 575)
  {
    throw MyException2("Error 2 occured because a == 575.");
  }

}
catch (MyException1 &ex)
{
  std::cout << "Exception 1: " << ex.what() << "\n";
}
catch (MyException2 &ex)
{
  std::cout << "Exception 2: " << ex.what() << "\n";
}

Note: This is an easy but not the best design for a custom exception since std::string may throw and your program will be terminated.

2. You want two different error messages:

Use the appropriate type of exception from <stdexcept> header:

try
{

  int a = 5;
  // do stuff
  if (a == 7)
  {
    throw std::runtime_error("Error 1 occured because a == 7.");
  }
  else if (a == 5)
  {
    throw std::runtime_error("Error 2 occured because a == 5.");
  }

}
catch (const std::exception &ex)
{
  std::cout << "Exception: " << ex.what() << "\n";
}

Note: The behaviour of case 1 can be emulated in case 2 without own types if the only desired behaviour is different output:

try
{

  int a = 5;
  // do stuff
  if (a == 7)
  {
    throw std::runtime_error("Exception 1: Error 1 occured in  because a == 7.");
  }
  else if (a == 5)
  {
    throw std::runtime_error("Exception 1: Error 1 occured because a == 5.");
  }
  // do more stuff
  if (a == 22)
  {
    throw std::runtime_error("Exception 2: Error 2 occured in  because a == 22.");
  }
  else if (a == 575)
  {
    throw std::runtime_error("Exception 2: Error 2 occured because a == 575.");
  }

}
catch (const std::exception &ex)
{
  std::cout << ex.what() << "\n";
}
Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
2

Use std::runtime_error it has a constructor that takes a string. So pass it a different value when it is throw.

 throw runtime_error( "msg1");

 ...

 throw runtime_error("msg2");

Then when you catch just print the message in the object

 ...
 catch( exception& e ){
     cout << e.what() << endl;
 }
Charlie OConor
  • 857
  • 1
  • 9
  • 18
  • It seems the same as throwing std::string because you can't differentiate between two exception without analysing string text. – Pustovalov Dmitry Feb 21 '16 at 21:14
  • 1
    You want to avoid throwing strings since they could also throw exceptions. If you have to exceptions going at once it will crash you're program. It is clear and more idomaticly correct to throw runtime erros. As you can see it is cautgh by a refference to excetipn. String doesn't inherit from exception and would not be cauth there. To properly integrate you're code with someone elses any thrown object should inherit form std::exception. http://stackoverflow.com/questions/134569/c-exception-throwing-stdstring – Charlie OConor Feb 21 '16 at 21:18
0

First: Your compiler is supposed to issue a warning for that, because, the second catch will never be executed, because they are of exact signatures. Besides, you cannot have a second exception being thrown while the first is active ( exception thrown during stack unwinding that hasn't entered a catch block yet), else, the runtime will terminate your program.

Secondly: prefer to catch your exceptions by reference

Thirdly: Prefer to have your exception object fall in the inheritance tree of std::exception.

Lastly: What the hell are you trying to do?

WhiZTiM
  • 21,207
  • 4
  • 43
  • 68
  • *Besides, you cannot have a second exception being thrown while the first is active, else, the runtime will terminate your program.* - That doesn't sound correct, but I'm not sure what you are trying to say. You can of course throw an exception from within a `catch` block. What you cannot do is throw an exception from a destructor during the stack unwinding caused by a `throw`. – Christian Hackl Feb 21 '16 at 21:16
  • That was largely what I was trying to say. Thanks, let me correct my answer to clarify – WhiZTiM Feb 21 '16 at 21:17