There are lots of design decisions with C++, C#, and Java that in hindsight are poor, but I don't feel like the author focused on the problematic parts, and maybe confused/conflated encapsulation and abstraction.
In my opinion, this style of OO can be best described by:
the ability to bundle data (something like a struct or record) and operations on that data (methods, which are essentially functions with an implicit "this" argument) into classes
the ability to extend classes via inheritance, and automatically and irrevocably get subtype polymorphism, which can be ad-hoc through overrides
the ability to hide implementation details within a class (private fields & methods)
Additional ad-hoc polymorphism via interfaces
I don't think I have a problem with a language having any of those features.
I don't know if bundling data and operations is helpful, but I certainly don't think having the option is harmful. I do appreciate that the <class instance>.<method>() syntax is ergonomic. This can also be achieved by "." being syntax sugar where <expression>.<function>(...args) is equivalent to function(expression, ...args).
I do think it's a problem when developers shoehorn their data types into convoluted inheritance hierarchies, but this isn't an OO problem. It's equally problematic when developers shoehorn data types into any convoluted data representation. I acknowledge that there may be some times where the type extension along with the subtype polymorphism may be an elegant representation.
Hiding implementation details is not something I see as problematic at all, and it's not unique to OO languages. Other languages allow private struct fields and other definitions that are only usable inside the module where they're defined.
It's nice when languages have something more powerful than these style of interfaces like Rust's traits or Haskell's typeclasses, but I don't think that makes interfaces bad, maybe just less useful.
The big problems with these languages are:
null - Anywhere you expect a class instance you must also expect the possibility of null. Terrible!
unchecked exceptions - effectively an implicit potential return type of every function you write. Terrible!
lack of type-safe sum-types/discriminated unions/tagged unions. Abstract parent class and multiple concrete children, the OO equivalent, is comparatively clunky. Scala's case classes are a nice implementation with an OOish flavor.
lack of robust treatment of functions as data (this is improving as functional concepts are making their way into other languages)
inability to extend the functionality of classes without subtyping
Unsoundness in Java's type system via inappropriate generic covariance
C++ being enormous and complicated
loads of safety issues in C++, but it should get a partial pass for being a lower level language
C++'s lack of package manager - this is an ecosystem problem, not a language problem
verbosity
What are the alternatives?
Maybe<T> instead of null (a generic sum type which is either T or nothing. It must be cased on)
Result<T, Error> instead of exceptions (another generic sum type that is either T or an error. It must be cased on, and what an "error" is a different language decision)
Give the option for sum-types! Please LabVIEW!
Give facilities for functions as data, lambda functions, partial application, etc.
Rust-style traits, typeclasses
Appropriate generic covariance/contravariance (invariance if you can't be sound otherwise - restrictive is better than unsound)
Good package managers & build systems
type inference
What languages do these things well that are easy to use? In my opinion: TypeScript, F#, and Scala, which all also support OO stuff. Rust is probably my favorite language, but it is not easy. Haskell is great as a learning experience, but is definitely difficult and is so high level that it makes it hard to reason about when your program will do what at runtime because of laziness.