0
\$\begingroup\$

I myself is a Java-developer and now I'm trying to understand how to do it in the most efficient way in C++. After reading that answer I decided to write the following:

//Headers omitted
class integer_validator
{
public:
    integer_validator(const char* const str);
    bool is_valid();
    long get_number();
private:
    bool valid;
    long result;
};

integer_validator::integer_validator(const char* const str)
{ 
    char *endptr;
    result = strtol(str, &endptr, 10);
    if(*endptr == '\0') valid = true;
    else valid = false;
}

bool integer_validator::is_valid()
{
    return valid;
}

long integer_validator::get_number()
{
    if(!valid)
        throw std::exception();
    return result;
}
int main ()
{
    integer_validator vv("123123");
    integer_validator v("123123a");
    std::cout << vv.get_number() << std::endl; //prints the number
    std::cout << v.get_number() << std::endl;  //throws the exception
}

DEMO

And it works perfectly fine. But I'm not sure about some things I did. Is it considered good to put any piece of logic into a constructor? I actually do the validation within the constructor's body and I use only the C-functions.

So should I be afraid of throwing an exception during the construction in that case?

\$\endgroup\$
  • \$\begingroup\$ Why do you pass the string to the constructor? It looks weird and counter-intuitive. You would expect a validator objects to be able to check many strings.. well, at least I would... \$\endgroup\$ – Karoly Horvath Jun 20 '15 at 16:06
  • \$\begingroup\$ @KarolyHorvath So what should I pass to then? I thought that it looks good because the purpose of that class is to validate if the string represent a number. \$\endgroup\$ – St.Antario Jun 20 '15 at 16:08
  • \$\begingroup\$ Nothing.......? \$\endgroup\$ – Karoly Horvath Jun 20 '15 at 16:08
  • \$\begingroup\$ @St.Antario In case of integer validation you could pass some validation parameters, e.g. the limits of valid integer values: integer_validator::integer_validator(int lower_bound, int upper_bound) \$\endgroup\$ – Oleg Andriyanov Jun 20 '15 at 16:14
1
\$\begingroup\$
if(*endptr == '\0') valid = true;
else valid = false;

would be better as just

valid = *endptr == '\0';

(or maybe even valid = !*endptr;, in the traditional C style).

Note that this isn't a sufficient check.

|improve this answer|||||
\$\endgroup\$
2
\$\begingroup\$

From the c++ specification's point of view a constructor is allowed to throw an exception (in opposite to destructor). So your code is fine.

On the other hand I don't see any advantage why it should be validated directly in the constructor. You could do it in is_valid method as well. Furthermore, if you moved the valifation code out from the constructor to a private method, you would gain an easy way to keep responsibility of handling low-level exceptions inside you class. So, although your code is valid semantically, its design needs some improvement.

I hope I helped:)

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ "... c++ specification's point of view a constructor is allowed to throw an exception (in opposite to destructor)." For practical purposes, this is good advice to follow (don't throw from a destructor), but the C++ specification does not disallow throwing from a destructor. Throwing from a destructor is perfectly valid. It just doesn't have very safe or useful behavior since the program will terminate if an exception is thrown in a destructor while an exception is already propogating. \$\endgroup\$ – Corbin Jun 20 '15 at 19:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.