Reputation: 1263
Consider the following example where the construction of Derived
class takes a pointer on its constructor's initializer list. Of course I want to check if this pointer is valid and throw an exception otherwise.
My attempt prevents the program to crash but Base
part is still constructed before I can throw the exception.
Is there a way I can prevent Base
class constructor being called in this case ?
#include <stdlib.h>
#include <iostream>
class Base
{
public:
Base(int val) : val_b(val)
{
std::cout << "Base::CTOR" << std::endl;
}
~Base() { }
int val_b;
};
class Derived : public Base
{
public:
Derived(int *, int);
~Derived() { }
int val_d;
void print(void)
{
std::cout << "Base:\t" << val_b << std::endl;
std::cout << "Derived:" << val_d << std::endl;
}
};
Derived::Derived(int *val1, int val2) : Base(val1 ? *val1 : -1), val_d(val2)
{
if (!val1)
{
throw std::invalid_argument("bad pointer");
}
}
int main()
{
int *a = NULL;
int b = 43;
try
{
Derived *d = new Derived(a, b);
d->print();
}
catch (std::exception &e)
{
std::cout << "Exception: " << e.what() << std::endl;
}
return 0;
}
Upvotes: 0
Views: 230
Reputation: 217398
You might call a function/lambda before calling Base constructor:
Derived::Derived(int *val1, int val2) :
Base([&](){
if (!val1) {
throw std::invalid_argument("bad pointer");
}
return *val1;
}()),
val_d(val2)
{
}
Upvotes: 4
Reputation: 1529
I don't get why you want it but anyway have you tried failing in Base ctor rather than Derived ctor?
class Base
{
public:
Base(int *val)
{
if (!val)
{
throw std::invalid_argument("bad pointer");
}
val_b = val;
std::cout << "Base::CTOR" << std::endl;
}
~Base() { }
int val_b;
};
Upvotes: 0
Reputation: 122516
Maybe I misunderstand your question, but consider this simplified example:
#include <iostream>
struct Base {
~Base() { std::cout <<"destructor";}
};
struct Foo : Base {
Foo() : Base() {
throw 1;
}
};
int main()
{
try {
Foo f;
} catch(...){}
}
Output is:
destructor
My attempt prevents the program to crash but Base part is still constructed before I can throw the exception.
That isn't a problem. As always with exceptions, stack is unwinded and the Base
part of Foo
is properly destroyed. I see nothing wrong in your code (in the sense of seriously broken, though design is debatable). If construction fails and you throw an exception in the body of the constructor, cleaning up what already has been constructed is the best you can do.
Upvotes: 0