For finer-grained control of your input routines, you need to learn to use the std::ios_base::iostate stream states goodbit, eofbit, badbit, and failbit. You can either check the states directly with std::basic_ios::rdstate or use the convenient member functions .good(), .eof(), .bad() and .fail(), see std::basic_istream.
While checking .good() will tell you you have good input, it doesn't help you recover from failed input or an error condition or EOF. For that you have to individually check the error condition that occurred.
Continuing from my comment and adding a bit of detail, you could do something like the following (where you are just doing the same thing for both a and b -- which could you could move to a function or member function), e.g.
#include <iostream>
#include <limits>
int main (void) {
    int a, b;
    /* get input for a */
    while (1)       /* loop continually reading input */
    {
        std::cout << "\nenter an integer for a: ";
        if (! (std::cin >> a) ) {   /* check stream state */
            /* if eof() or bad() break read loop */
            if (std::cin.eof() || std::cin.bad()) {
                std::cerr << "(user canceled or unreconverable error)\n";
                goto unrecoverable;
            }
            else if (std::cin.fail()) {     /* if failbit */
                std::cerr << "error: invalid input.\n";
                std::cin.clear();           /* clear failbit */
                /* extract any characters that remain unread */
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(),
                                '\n');
            }
        }
        else {  /* on succesful read, just output int and break loop */
            std::cout << "integer a: " << a << '\n';
            /* extract any characters that remain unread */
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(),
                            '\n');
            break;
        }
    }
    /* same thing for b */
    while (1)       /* loop continually reading input */
    {
        std::cout << "\nenter an integer for b: ";
        if (! (std::cin >> b) ) {   /* check stream state */
            /* if eof() or bad() break read loop */
            if (std::cin.eof() || std::cin.bad()) {
                std::cerr << "(user canceled or unreconverable error)\n";
                break;
            }
            else if (std::cin.fail()) {     /* if failbit */
                std::cerr << "error: invalid input.\n";
                std::cin.clear();           /* clear failbit */
                /* extract any characters that remain unread */
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(),
                                '\n');
            }
        }
        else {  /* on succesful read, just output int and break loop */
            std::cout << "integer b: " << b << '\n';
            /* extract any characters that remain unread */
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(),
                            '\n');
            break;
        }
    }
    unrecoverable:;
}
Note the use of std::numeric_limits<std::streamsize>::max() used with std::cin.ignore to clear any offending characters that are left in stdin. (which essentially extracts up to the maximum streamsize of characters until an '\n' is found) Necessary so you next input attempt does not attempt to re-read the same bad characters and fail again for the same reason -- generally resulting in an infinite loop if input is taken within a loop.
Also note the use of the good old goto to allow for a graceful exit from the program regardless whether the user cancels input for a or b.
It's an input routine, so after you write it -- go try and break it. If it breaks, fix it. That about the only way you can catch most corner-cases, e.g.
Example Use/Output
$ ./bin/cin_validate_ab
enter an integer for a: no
error: invalid input.
enter an integer for a: OK
error: invalid input.
enter an integer for a: 5, I entered 5!
integer a: 5
enter an integer for b: again!
error: invalid input.
enter an integer for b: 6
integer b: 6
User canceling input with Ctrl+d on Linux (or Ctrl+z on windows).
$ ./bin/cin_validate_ab
enter an integer for a: (user canceled or unreconverable error)
Look thing over and let me know if you have questions.