C++中如何区分OBJ、OBJ&、const OBJ&并实现同名方法多态?
OBJ o, OBJ& o, and const OBJ& o in Catch Blocks for Different Implementations Absolutely! You can easily trigger different logic for the same operation name when catching exceptions by value, non-const reference, or const reference. You don’t even need inheritance or polymorphism—C++’s function overloading and ref-qualified member functions are perfect for this. Here are two straightforward approaches tailored to your needs:
Approach 1: Non-Member Function Overloading (Simplest)
This uses plain old function overloading to match the exact catch parameter type. The same doSomething name will resolve to the correct implementation automatically.
#include <iostream> class OBJ {}; // Triggered when catching by value (OBJ o) void doSomething(OBJ) { std::cout << "Action 1: Caught exception by value\n"; } // Triggered when catching by non-const reference (OBJ& o) void doSomething(OBJ&) { std::cout << "Action 2: Caught exception by non-const reference\n"; } // Triggered when catching by const reference (const OBJ& o) void doSomething(const OBJ&) { std::cout << "Action 3: Caught exception by const reference\n"; } // Program 1: Catch by value int main() { try { throw OBJ{}; } catch(OBJ o) { doSomething(o); // Calls value overload } return 0; } // Program 2: Catch by non-const reference // int main() { // try { // throw OBJ{}; // } catch(OBJ& o) { // doSomething(o); // Calls non-const ref overload // } // return 0; // } // Program 3: Catch by const reference // int main() { // try { // throw OBJ{}; // } catch(const OBJ& o) { // doSomething(o); // Calls const ref overload // } // return 0; // }
Just uncomment the relevant main function for each program—no other code changes needed.
Approach 2: Member Functions with Ref-Qualifiers (Matches Your Original Code Structure)
If you prefer calling o.doSomething() as a member function (like your code example), you can use C++11+ ref-qualified member functions to distinguish between lvalues (references) and rvalues (moved value copies):
#include <iostream> #include <utility> // For std::move class OBJ { public: // For non-const lvalue references (catch(OBJ& o)) void doSomething() & { std::cout << "Action 2: Caught by non-const reference\n"; } // For const lvalue references (catch(const OBJ& o)) void doSomething() const& { std::cout << "Action 3: Caught by const reference\n"; } // For rvalues (we convert the value catch to an rvalue with std::move) void doSomething() && { std::cout << "Action 1: Caught by value\n"; } }; // Program 1: Catch by value int main() { try { throw OBJ{}; } catch(OBJ o) { std::move(o).doSomething(); // Calls rvalue-qualified member } return 0; } // Program 2: Catch by non-const reference // int main() { // try { // throw OBJ{}; // } catch(OBJ& o) { // o.doSomething(); // Calls non-const lvalue member // } // return 0; // } // Program 3: Catch by const reference // int main() { // try { // throw OBJ{}; // } catch(const OBJ& o) { // o.doSomething(); // Calls const lvalue member // } // return 0; // }
How This Works:
- The
&qualifier on a member function means it can only be called on lvalue objects (like references). - The
const&qualifier works on const lvalue objects (const references). - The
&&qualifier works on rvalue objects—by usingstd::move(o)on the value-caught object, we treat it as an rvalue, triggering this version.
Both approaches let you reuse the same core code across all three programs—just swap out the catch parameter type (and std::move for the member function approach) to get different behavior.
内容的提问来源于stack exchange,提问作者Dean

