C ++ Constructor ignore exceptions

I searched for SO to answer this question, but did not find it.

When an object throws an exception at the end of the constructor, is the object valid or does one of them “depend on the construction technique”?

Example:

    struct Fraction
    {
      int m_numerator;
      int m_denominator;
      Fraction (double value,
                int denominator);
    };
    Fraction::Fraction(double value, int denominator)
    :  m_numerator(0), m_denominator(denominator)
    {
      if (denominator == 0)
      {
/* E1 */        throw std::logic_error("Denominator is zero.");
      }
      m_numerator = static_cast<int>(value * static_cast<double>(denominator));
      double actual_value = 0.0;
      actual_value = static_cast<double>(m_numerator) / static_cast<double>(m_denominator);
      double error = fabs(actual_value - value);
      if (error > 5.0E-5)
      {
/* E2 */  throw std::logic_error("Can't represent value in exact fraction with given denominator");
      }
    }

Program:

int main(void)
{
    try
    {
        Fraction f1(3.14159264, 4); // Throws exception, E2 above.
    }
    catch (...)
    {
        cerr << "Fraction f1 not exactly representable as fraction with denom. of 4.\n";
    }

    // At this point, can I still use f1, knowing that it is an approximate fraction?

    return EXIT_SUCCESS;
}

In this example, can f1 be used after the exception is caught knowing that this is an approximate value?

Data items have been created and initialized.

I do not see any C ++ language rule that is violated above.

Edit: Changed error delta value from 5.0E05 to 5.0E-5.

+5
source share
9 answers

. , , , . is_exactly_representable API , bool.

+4

f1 . , .

+5

, , f1 , . , :

try
{
    Fraction f1(3.14159264, 4); // Throws exception, E2 above.

    // f1 can be used until here
}
catch (...)
{
}

// The scope that f1 was defined in is over, so the compiler will not let
// you reference f1

, , , . , , :

enum FractionOption { disallowInexact, allowInexact };

Fraction::Fraction(double value, int denominator,
                   FractionOption option = disallowInexact)
{
    ...
    if ((option == disallowInexact) && (error > 5.0E-5))
    {
        throw std::logic_error("Can't represent value ...");
    }
}

Fraction f1(3.14159264, 4, allowInexact);
+2

throw in constructor = →

, , . , :

f = new Fraction(3.14159264, 4);

f , , . , , .

, , , . is_exact(), , .

+2

fbrereto.

, , " " " ", - , , , , , , MySettingsReader.

+1

JMD

TH1 f1 catch. . , , .

, , , , - ,

+1

, , " "?

, . , , . .

, , , . , , , , .

, , , ++/15.2:

, , .. , .

, , not.

#include <iostream>
using namespace std;
struct A
{
    ~A() { cout<<"~A()\n"; }
};
struct B
{
    A a;
    B() { throw 1; }
    ~B() { cout<<"~B()\n"; } // never called
};
int main()
{
    try
    {
        B a;
    }
    catch (...)
    {
        cout << "caught\n";
    }
}
+1

, . f1 .

f1 , try, ( ) , . , , ; , , .

, , , . , .

0

( ), . -, , . - , -, , , .

, , RAII , , . ptr = new Foo(); ptr . smartptr.reset(new Foo()); reset.

Pay attention to the fallacy of using the new operator in expressions that construct other objects: somefunc(Foo(), new Bar());. If the Foo constructor fails, a memory leak may occur (depending on the order in which your compiler processed the arguments).

0
source

All Articles