The key problem is that you provide no assignment constructor. Consequently, the compiler generate a default one for you:
X& X::operator =(const X& x){
this.member = x.member;
return *this;
}
The default assignment constructor accepts argument type as const X& in which the const is a low-level const and won't be ignored as top-level const.
Your code X b = a
means to call the default constructor. But your argument a
has type volatile X (can be converted to volatile X & and volatile const X &) cannot be converted to const X& implicitly.
So you should define your own assignment constructor as
X& X::operator =(volatile const X&);
EDIT
It shocks me that so many guys think the copy constructor (or call copy initialization) is called when using assignment operator.
Maybe call it assignment operator is not common. However, what I care is which method is called.
You can refer to this post:Copy constructors, assignment operators, and exception safe assignment and Default assignment operator
EDIT
I made a mistake previously.
X b = a
is just a initialization process. No assignment is involved.
Apologize for my error message.