In my opinion, message passing is a requirement of encapsulation. If telling a object to do something that it doesn't understand can break a program, then the object isn't completely encapsulated.
Nonsense. Programming by contract or not has nothing to do with OOP. Also, allowing the compiler to catch errors the runtime would otherwise catch does also have it's advantages.
Furthermore, since c++ doesn't natively support reflection or dynamic typing
C# does, which uses the same method calling paradigm as C++.
the programmer must always be aware of exactly what class each object is, which doesn't seem like pure encapsulation to me either.
Yes it is. Because the programmer doesn't need about the actual implementation of the object. It only needs it's interface. Which has it's advantages, because you know which "messages" it understands and what parameters you can give those messages.
Besides, it would be very easy in C++ to devise objects that actually uses message passing rather than method calling, if you find that more attractive. But that doesn't make it any more OOP.
The point is that c++ really isn't much different from c, just sometimes more convenient.
That's why OOP is a design paradigm, and has nothing to do with syntax. You can design an OOP program in C just fine.
In c we would write...
Rabbit* myRabbit = rabbit_new();
In c++ we would instead write...
Rabbit* myRabbit = new Rabbit();
Are these not exactly the same?
As is with any language. What's your point?