Suppose the following example. There are classes A-C derived from std::exception:
#include <exception>
#include <string>
#include <iostream>
class A : public std::exception {
std::string a_text;
public:
A(const std::string & a_text_) : a_text(a_text_) {}
virtual ~A() throw() { }
};
class B : public A {
const std::string b_text;
public:
B(const std::string &a_text_, const std::string & b_text_) : A(a_text_), b_text(b_text_) {}
virtual ~B() throw() {}
};
template <typename T>
class C : public B {
T x;
public:
C(const std::string & a_text_, const std::string & b_text_, const T x_) :
B (b_text_, a_text_), x(x_) { }
virtual ~C() throw() {};
};
So far I have been convinced that generalizing pattern catches the exception of the derived class in multiple blocks.
int main() {
try {
throw C<double>("a", "b", 10);
}
catch (C<double> &c1) {
std::cout << " C";
}
catch (B &b1) {
std::cout << " B";
}
}
Unfortunately, the second block referring to B is skipped. Where is the problem? Thanks for your help.
Only the first catch block that matches is going to execute. You can re-throw the existing exception with the "throw;" statement but I am not sure if that will continue the search at the next catch block or only in a outer try-catch.
Related
I would like to create a base class ==> derived class setup where the base class' constructor has a callback to run a (possibly complex) function to modify the base class' private member with information from the derived class. However, I'm running into a chicken and an egg problem because the base class constructor runs before the derived class' members are initialized. Here's the code to demonstrate the problem:
#include <iostream>
#include <functional>
class B
{
public:
typedef std::function<void(std::string &)> mod_func_t;
B(const mod_func_t &m) : foo("base str")
{
std::cout << "Base constructor\n";
m(foo);
std::cout << "base constructor finally has: " << foo << std::endl;
}
private:
std::string foo;
};
class D : public B
{
public:
D(const std::string &input) :
B(std::bind(&D::my_f, this, std::placeholders::_1)),
input_(input)
{
std::cout << "Derived constructor\n";
}
private:
void my_f(std::string &s)
{
std::cout << "Derived class' modification function\n";
s += input_; // <== Crashes here because input_ is not yet constructed
}
const std::string input_;
};
int main()
{
D d("my input");
return 0;
}
What is the correct way to do this?
One approach is to let D calculate the adjusted string before calling the constructor of B.
class D : public B {
D(std::string str)
: B(my_f(str))
{}
std::string my_f(std::string str) { return str + "..."; }
};
A second approach is to let the body of constructor D do some work. Here adjust_base could also be virtual.
class D : public B {
D(std::string str)
: B(str)
{
adjust_base();
}
void adjust_base();
};
I believe that CRTP could help you with this one..
There is a simple example:
#include <iostream>
#include <functional>
template <typename Derived>
class B
{
public:
B() : foo("base str")
{
static_cast<Derived*>(this)->m(foo);
std::cout << "Base constructor\n";
std::cout << "base constructor finally has: " << foo << std::endl;
}
void m(std::string& str) { //... }
private:
std::string foo;
friend Derived;
};
class D : public B<D>
{
public:
D(std::string &input) :
B(),
input_(input)
{
std::cout << "Derived constructor\n";
}
void m(const std::string& str) { //... }
private:
void my_f(std::string &s)
{
std::cout << "Derived class' modification function\n";
s += input_; // <== Crashes here because input_ is not yet constructed
}
const std::string input_;
};
int main()
{
D d("my input");
return 0;
}
Suppose the following example. There are classes A-C derived from std::exception:
#include <exception>
#include <string>
#include <iostream>
class A : public std::exception {
std::string a_text;
public:
A(const std::string & a_text_) : a_text(a_text_) {}
virtual ~A() throw() { }
};
class B : public A {
const std::string b_text;
public:
B(const std::string &a_text_, const std::string & b_text_) : A(a_text_), b_text(b_text_) {}
virtual ~B() throw() {}
};
template <typename T>
class C : public B {
T x;
public:
C(const std::string & a_text_, const std::string & b_text_, const T x_) :
B (b_text_, a_text_), x(x_) { }
virtual ~C() throw() {};
};
So far I have been convinced that generalizing pattern catches the exception of the derived class in multiple blocks.
int main() {
try {
throw C<double>("a", "b", 10);
}
catch (C<double> &c1) {
std::cout << " C";
}
catch (B &b1) {
std::cout << " B";
}
}
Unfortunately, the second block referring to B is skipped. Where is the problem? Thanks for your help.
Only the first catch block that matches is going to execute. You can re-throw the existing exception with the "throw;" statement but I am not sure if that will continue the search at the next catch block or only in a outer try-catch.
I have two functions a() and b(), which are having own exception classes (consecutively a_exc and b_exc) that inherit from std::logic_error.
void a() { (...) throw a_exc(some_val) }
void b() { (...) throw b_exc(some_val) }
class a_exc : public std::logic_error
{
private:
int foo;
public:
a_exc(int val, const std::string& what_msg="Msg.")
: std::logic_error(what_msg), foo(val) {}
void show() { //show foo }
}
class b_exc : public std::logic_error
{
private:
std::string bar;
public:
a_exc(std::string val, const std::string& what_msg="Msg.")
: std::logic_error(what_msg), bar(val) {}
void show() { //show bar }
}
Let's say I have following part of code:
try {
a();
b();
}
catch (const std::logic_error& e)
{
e.what();
// e.show();
}
catch (const std::logic_error& e) catches both a_exc and b_exc. Of course this block cannot use e.show(), because catched obj is std::logic_error.
And here's my problem. I wonder if there is any chance to call show() method in std::logic_error catch block when catched exception was a_exc or b_exc. I know, calling show() is possible if I create separate catch blocks for a_exc and b_exc, but I want to call this method with using just one catch block. Is it possible?
You can, provided that show() is a const member function:
catch (const std::logic_error& e)
{
e.what();
if(const a_exc* a = dynamic_cast<const a_exc*>(&e))
a->show();
else if(const b_exc* b = dynamic_cast<const b_exc*>(&e))
b->show();
}
See it Live on Coliru. Though, it's usually a bad idea to call other functions that may throw in your catch exception handler.
Some thoughts on design.
Querying the type of exception within the catch block is logically no different to simply providing two catch blocks.
To be clear:
catch(X& x)
{
if (dynamic_cast<Y*>(&x)) {
// it's a Y
}
if (dynamic_cast<Z*>(&z)) {
// it's a Z
}
else {
// it's an X
}
}
is logically the same as:
catch(Y& t)
{
// it's a Y
}
catch(Z& z)
{
// it's a Z
}
catch(X& x)
{
// it's an X
}
Except that the second is clearer, more maintainable and resistant to inadvertent slicing on a subsequent copy.
The first is using "code to find code", which is always a maintenance disaster waiting to happen.
Your question raises more questions of its own:
Are a_exc and b_exc two kinds of the same error? If so, this argues for a polymorphic base class, which you can catch in preference to std::logic_error
Do you really need the show() method? Can you simply build the what string in the constructor, and pass this string to the constructor of std::logic_error? If this is at all possible, it is the route I would recommend. The moment you start adding special interfaces to exceptions, you pollute your entire code base with the necessity of knowing about this interface. If you're writing a library, you've now polluted every application that uses your library.
Assuming you do need show, and a_exc and b_exc really are two kinds of the same error, we can still avoid polymorphism. Perhaps we can shore the 'show' message as a string, and build it in the constructor. Now it's just data. No fuss, no complication.
(complete) example using polymorphic base class (a_exc an b_exc are kinds of the same thing)
#include <stdexcept>
#include <string>
struct showable_logic_error : std::logic_error
{
using std::logic_error::logic_error;
virtual void show() const = 0;
};
class a_exc : public showable_logic_error
{
private:
int foo;
public:
a_exc(int val, const std::string& what_msg="Msg.")
: showable_logic_error(what_msg)
, foo(val)
{}
void show() const override
{
//show foo
}
};
class b_exc : public showable_logic_error
{
private:
std::string bar;
public:
b_exc(std::string val, const std::string& what_msg="Msg.")
: showable_logic_error(what_msg)
, bar(val)
{}
void show() const override
{ //show bar
}
};
void a() { throw a_exc(1); }
void b() { throw b_exc("b"); }
int main()
{
try
{
a();
}
catch(showable_logic_error const& e)
{
e.show();
}
}
complete example in which no polymorphism is required:
#include <stdexcept>
#include <string>
#include <sstream>
struct message_builder
{
template<class T>
static std::string build_what(const std::string& whatstr, T&& info)
{
std::ostringstream ss;
ss << whatstr << " : " << info;
return ss.str();
}
};
class a_exc
: public std::logic_error
, private message_builder
{
public:
a_exc(int val, const std::string& what_msg="Msg.")
: std::logic_error(build_what(what_msg, val))
{}
};
class b_exc
: public std::logic_error
, private message_builder
{
private:
std::string bar;
public:
b_exc(std::string val, const std::string& what_msg="Msg.")
: std::logic_error(build_what(what_msg, std::move(val)))
, bar(val)
{}
};
void a() { throw a_exc(1); }
void b() { throw b_exc("b"); }
int main()
{
try
{
a();
}
catch(std::logic_error const& e)
{
e.show();
}
}
You should consider creating a derived type:
struct show_exc : public std::logic_error
{
virtual void show() = 0;
};
class a_exc : public show_exc
{
int foo_;
public:
virtual void show() override { /*...*/ };
};
and then use a distinguishing catch:
catch (const show_exc& e) {
// ..
}
catch (const std::logic_error& e) {
// ..
}
class A{
public:
A(): b(), c(), d(){}
private:
B b;
C c;
D d;
};
I have something similar to above code. where the initialization list is longer than here. Somewhere things go wrong in the initialization of objects. I want to find out where did it go wrong; after what object and in the initialization of which object did it fail.
I dont want to do it adding print statements to the respective classes.
One way I thought of having a class temp which will print a line for me in its constructor; This way I need to have as many objects as the number of class variables in my class A. There is no segfault or any exception being thrown which I can catch.
So is there any other way I can debug this other than having a class temp with as many objects of temp as the member variables. Is there smart way to debug this. Thanks.
#include <exception>
#include <string>
#include <typeinfo>
#include <iostream>
struct B
{
};
struct C
{
};
struct D
{
};
struct YourExceptionType:std::exception
{ std::string m_s;
YourExceptionType(const std::string &_r)
:m_s(_r)
{
}
~YourExceptionType(void) throw()
{
}
const char *what(void) const throw()
{ return m_s.c_str();
}
};
struct Show
{ Show(const char *const _p)
{ std::cout << _p << std::endl;
}
};
template<typename A>
struct ShowMe:Show, A
{ ShowMe(void)
try:Show(typeid(A).name()),
A()
{
} catch (const std::exception &_r)
{ throw YourExceptionType(
(std::string("Failed constructor of type ")
+ typeid(A).name()
+ ":" + _r.what()).c_str());
}
};
class A{
public:
A(): b(), c(), d(){}
private:
ShowMe<B> b;
ShowMe<C> c;
ShowMe<D> d;
};
Please see the example code below:
class A
{
private:
class B
{
public:
foobar();
};
public:
foo();
bar();
};
Within class A & B implementation:
A::foo()
{
//do something
}
A::bar()
{
//some code
foo();
//more code
}
A::B::foobar()
{
//some code
foo(); //<<compiler doesn't like this
}
The compiler flags the call to foo() within the method foobar(). Earlier, I had foo() as private member function of class A but changed to public assuming that B's function can't see it. Of course, it didn't help. I am trying to re-use the functionality provided by A's method. Why doesn't the compiler allow this function call? As I see it, they are part of same enclosing class (A). I thought the accessibility issue for nested class meebers for enclosing class in C++ standards was resolved.
How can I achieve what I am trying to do without re-writing the same method (foo()) for B, which keeping B nested within A?
I am using VC++ compiler ver-9 (Visual Studio 2008). Thank you for your help.
foo() is a non-static member function of A and you are trying to call it without an instance.
The nested class B is a seperate class that only has some access privileges and doesn't have any special knowledge about existing instances of A.
If B needs access to an A you have to give it a reference to it, e.g.:
class A {
class B {
A& parent_;
public:
B(A& parent) : parent_(parent) {}
void foobar() { parent_.foo(); }
};
B b_;
public:
A() : b_(*this) {}
};
This is an automagic, albeit possibly nonportable trick (worked on VC++ since 6.0 though). Class B has to be a member of class A for this to work.
#ifndef OUTERCLASS
#define OUTERCLASS(className, memberName) \
reinterpret_cast<className*>(reinterpret_cast<unsigned char*>(this) - offsetof(className, memberName))
#endif
class A
{
private:
class B
{
public:
void foobar() {
A* pA = OUTERCLASS(A, m_classB);
pA->foo();
}
} m_classB;
public:
foo();
bar();
};
Basically what Georg Fritzsche said
#include <iostream>
#include <cstring>
using namespace std;
class A
{
private:
class B
{
A& parent_;
public:
//B(); //uncommenting gives error
~B();
B(A& parent) : parent_(parent) {}
void foobar()
{
parent_.foo();
cout << "A::B::foo()" <<endl;
}
const std::string& foobarstring(const std::string& test) const
{
parent_.foostring(test); cout << "A::B::foostring()" <<endl;
}
};
public:
void foo();
void bar();
const std::string& foostring(const std::string& test) const;
A();
~A(){};
B b_;
};
//A::B::B() {}; //uncommenting gives error
A::B::~B(){};
A::A():b_(*this) {}
void A::foo()
{
cout << "A::foo()" <<endl;
}
const std::string& A::foostring(const std::string& test) const
{
cout << test <<endl;
return test;
}
void A::bar()
{
//some code
cout << "A::bar()" <<endl;
foo();
//more code
}
int main(int argc, char* argv[])
{
A a;
a.b_.foobar();
a.b_.foobarstring("hello");
return 0;
}
If you uncomment the default B constructor you would get an error
If you want to reuse functionality from A then you should inherit from A not nest B inside it.
Combining Igor Zevaka's and enthusiasticgeek's answers. Also, using reinterpret_cast for calculating offset (If you create class member variable using new keyword):
#include <iostream>
#include <cstring>
using namespace std;
template < typename T, typename U > constexpr size_t offsetOf(U T:: *member)
{
return (char*) &((T*) nullptr->*member) - (char*) nullptr;
}
class A
{
private:
class B
{
public:
B(string message);
~B();
void foobar()
{
A *pA = reinterpret_cast<A*> (reinterpret_cast< unsigned char*> (this) - offsetOf(&A::b_));
pA->foo();
pA->bar();
std::cout << "DONE!";
}
};
public:
void foo();
void bar();
A();
~A() {};
B* b_ = new B("Hello World!");
};
A::A()
{
cout << "A constructor\n";
};
A::B::B(string message) {
cout << "B constructor\n";
cout << "Message = " << message << "\n";
};
A::B::~B() {};
void A::foo()
{
cout << "A::foo()" << endl;
}
void A::bar()
{
cout << "A::bar()" << endl;
foo();
}
int main(int argc, char *argv[])
{
A* a = new A();
a->b_->foobar();
return 0;
}
Output:
B constructor
Message = Hello World!
A constructor
A::foo()
A::bar()
A::foo()
DONE!
References:
https://stackoverflow.com/a/10607424/9524565
https://stackoverflow.com/a/3058382/9524565
https://stackoverflow.com/a/20141143/9524565