First, according to standard, 9.5 point 1, in a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.
In your case, as c is an int, there is no benefit of adding a member to the original union. Simply reuse one of the existing int. Or foresee in the union all possible tag members from the start.
What you could do however, is to define c as a reference, and assign it the address of a union member, keeping in mind that All non-static data members of a union object have the same address (§ 9.5/1):
class B : public A {
int& c; //<- Can this use the same storage as the union?
public:
B() : c(A::a) {}
void test() {
a = 10;
std::cout << "a=" << a << "; ";
std::cout << "c=" << c << "; ";
c = 20;
std::cout << "a=" << a << "; ";
std::cout << "c=" << c << "; ";
}
};
The constraitn of a signe active union member remains of course in force.
By the way, why isn't it possible to share the same union between base class and derived class ? Because the standard says:
Unless redeclared in the derived class, members of a base class are also considered to be members of the derived class (§ 10 point 2)
Nonstatic data members of a (non-union) class with the same access control are allocated so that later members have higher addresses within a class object. (§ 9.2 pt 13)
So the members of the derived class have a higher address than the members of the base class.
But All non-static data members of a union object have the same address (§ 9.5/1)
Hence it is not possible that members from the derived class belong to a union in the base class. QED.