Exclude catch output when returning a base class type reference?

I am writing a Windows application in C ++ and have encountered the following problem when dealing with exceptions.

I have a base exception class from which all other exceptions flow. In the base class, I have a method for reporting an error of any exception. Then this method returns an exception (via '* this').

Now the problem arises when I want to extend a derived exception, and later use it in a catch block. Since the extend method is declared in the base class, the catch block captures the base class instead of the derived class. Is there any way around this so that the correct derived class is found instead?

Here are some examples to illustrate the problem:


// DECLARATIONS

class BaseException {
    BaseException() { }

    Exception& extend( string message ) {
        // extend message

        return *this;
    }
}

class DerivedException : public BaseException {
    DerivedException() : Exception() { }
}



// RUNNING CODE

int main() {
    try {
         ...

         try {
             ...

             // Something goes wrong
             throw DerivedException( "message1" );
         }
         catch ( DerivedException& exc ) {
             throw exc.extend( "message2" );
         }
    }
    catch ( DerivedException& ) {
        // Here is where I *want* to land
    }
    }
    catch ( BaseException& ) {
        // Here is where I *do* land
    }
}

"" , , . , .

+3
4

extend() :

 catch ( DerivedException& exc ) {
     exc.extend( "message2" );
     throw;
 }

extend() , / .

+5

, - "BaseException &". "throw exc.extend()" .

, ; . OP .

class BaseException {
public:
    BaseException() { } 

    BaseException& extend( string message ) { 
        // extend message 

        return *this; 
    } 
}; 

class DerivedException : public BaseException { 
public:
    DerivedException() : BaseException() { } 
}; 



// RUNNING CODE 

int main() { 
   try { 

      try { 
         // Something goes wrong 
         throw DerivedException(); 
      } 
      catch ( DerivedException& exc ) { 
         throw exc.extend("A"); 
      } 
   } 
   catch ( DerivedException& ) { 
      // Here is where I *want* to land 
      int i = 0;
   } 
   catch ( BaseException& ) { 
      // Here is where I *do* land 
      int i = 0;
   }
}
0

, "

template <typename TExc>
class BaseException { 
    BaseException() { } 

    TExc& extend( string message ) { 
        // extend message 

        return (TExc) *this; 
    } 
} 

class DerivedException : public BaseException<DerivedException> { 
    DerivedException() : BaseException() { } 
}
0

DerivedException & DerivedException. , - , , .

class BaseException {
public:
    BaseException() { }

    virtual BaseException& extend( std::string message ) {
        // extend message

        return *this;
    }
};

class DerivedException : public BaseException {
public:
    virtual DerivedException& extend( std::string message ) {
        return *this;
    }
    DerivedException(std::string) : BaseException() { }
};



// RUNNING CODE

int main() {
    try {
         try {
             // Something goes wrong
             throw DerivedException( "message1" );
         }
         catch ( DerivedException& exc ) {
             throw exc.extend( "message2" );
         }
    }
    catch ( DerivedException& ) {
        std::cout << "DerivedException!";
    }
    catch ( BaseException& ) {
        std::cout << "BaseException!";
    }
    std::cin.get();
}

DerivedException!

0

Source: https://habr.com/ru/post/1760759/


All Articles