0

I have the following issue:

I want to delete a mother object if an exception is thrown inside the constructor of one of its members. How do I do that?

The following does NOT what I want. Just you have something to refer to...

#include <iostream>

struct A
{

    A(int i)
    :mem(0)
    {
        try{
            if(i > 9) throw 0;
        }catch(int x) { std::cout << "mem max size 9\n"; return;}
        mem = i;
    }

    int mem;
};

struct B
{
    B(int i)
    :mem(i)
    {
    }

    const A mem;

};

int main()
{

    B b1(2);
    B b2(10);

    std::cout << "b1: " << b1.mem.mem << std::endl;
    std::cout << "b2: " << b2.mem.mem << std::endl;

}

//~ output:
//~ mem max size 9
//~ b1: 2
//~ b2: 0

Edit

Following this link I changed my code as follows

#include <iostream>

struct A
{

    A(int i)
    :mem(0)
    {
        if(i > 9) throw 0;
        else mem = i;
    }

    int mem;
};

struct B
{
    B(int i)
    try
    :mem(i)
    {
    }
    catch(int e)
    {
        std::cerr << "Error #" << e << std::endl;
    }

    const A mem;
};

int main()
{
    B b1(2);
    B b2(10);
}

//~ output:
//~ Error #0
//~ terminate called after throwing an instance of 'int'
//~ Aborted

But, I don't want the program to abort... how can I prevent that?

If I do it like this, the program does not get aborted but the B object is being constructed despite the exception...

#include <iostream>

struct A
{

    A(int i)
    :mem(0)
    {
        try
        {
            if(i > 9) throw 0;
        }
        catch(int e)
        {
            std::cerr << "A Error #" << e << std::endl; return;
        }
         mem = i;
    }

    int mem;
};

struct B
{
    B(int i)
    try
    :mem(i)
    {
    }
    catch(int e)
    {
        std::cerr << "Error #" << e << std::endl;
    }

    const A mem;
};

int main()
{

    B b1(2);
    B b2(10);

    std::cout << "b1: " << b1.mem.mem << std::endl;
    std::cout << "b2: " << b2.mem.mem << std::endl;

}

//~ A Error #0
//~ b1: 2
//~ b2: 0

and if I re-throw in the catch in A the program gets aborted again...

lo tolmencre
  • 3,804
  • 3
  • 30
  • 60
  • 1
    Because you caught the exception in A, the constructor of B does not get the exception. You could try re-throwing the exception after the message output in A's constructor. – Richard Critten Sep 17 '15 at 13:00
  • okay, but how can I catch it from B's initialiser list? – lo tolmencre Sep 17 '15 at 13:02
  • There is a syntax for it (can't remember it at the moment). Hopefully someone else can answer that part for you. try http://stackoverflow.com/questions/2441009/how-to-catch-the-exception-in-initialization-list – Richard Critten Sep 17 '15 at 13:03
  • [How to catch the exception in initialization list?](http://stackoverflow.com/questions/2441009/how-to-catch-the-exception-in-initialization-list) – MicroVirus Sep 17 '15 at 13:05
  • You shouldn't be catching the exception straight after you throw it. Use a try-block in `main()`. – juanchopanza Sep 17 '15 at 13:06
  • If construction of `B::mem` fails, construction of `B` also fails. It doesn't need to (can't, actually) delete itself because it doesn't exist. – molbdnilo Sep 17 '15 at 13:36

1 Answers1

3

The constructor for B isn't getting the exception because the constructor for A is catching it. Get rid of the try block there:

A(int i)
:mem(0)
{
    if(i > 9) {
        std::cout << "mem max size 9\n";
        throw 0;
    }
    mem = i;
}

If you attempt to catch the exception in the initializer list for B, it will get re-thrown anyway, so instead of catching the exception there, catch it in main:

int main()
{
    try {
        B b1(2);
        std::cout << "b1: " << b1.mem.mem << std::endl;
    } catch (int e) {
        std::cout << "failed to create b1" << std::endl;
    }
    try {
        B b2(10);
    } catch (int e) {
        std::cout << "failed to create b2" << std::endl;
    }
}
dbush
  • 205,898
  • 23
  • 218
  • 273
  • I see... hm But I want this to be a fix property of B. B shall delete itself if A cannot be constructed according to some condition. Is there no way to make this a built in thing of B? – lo tolmencre Sep 17 '15 at 13:13
  • @lotolmencre Afraid not. See [this link](http://gotw.ca/gotw/066.htm) for more details. – dbush Sep 17 '15 at 13:16
  • Thanks, I read the article and actually it does sound like the thing I want... but its not quite working yet. I updated my question post with the new code. – lo tolmencre Sep 17 '15 at 18:22
  • @lotolmencre It won't do what you want. Any exception caught from the initializer list automatically gets re-thrown if you don't throw it yourself. You need to use a `try..catch` block in `main` like my example shows. – dbush Sep 17 '15 at 18:40
  • Ok, I reread and figured I had that impression due to wishful reading.Thank you. – lo tolmencre Sep 17 '15 at 18:51