Odysseus
Odysseus

Reputation: 1263

Prevent Base class constructor being called on invalid Derived class initializer

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

Answers (3)

Jarod42
Jarod42

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

theWiseBro
theWiseBro

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

463035818_is_not_an_ai
463035818_is_not_an_ai

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

Related Questions