I don't think one can give a definitive answer, because there is significant debate nowadays about what Object Oriented design actually is. I will try to outline somewhat of a consensus below, and point out where my own opinion dissents.
Established OOP has its roots in studies in the early 1970s discussing principles, methods & patterns for dealing with complex code - such as the principle of Separations of Concerns (Dijkstra) (while aware that Smalltalk was around before that, I believe that this particular leap in theoretical understanding stands at the foundation of today's OOP). In pure object-oriented design, each type of object (class) should represent a singular/atomic idiom qualifying a relevant aspect of your solution, because OOP is an orthodox practical implementation of SoC theory. Therefore, as a generic rule of thumb, if you are describing a solution, and can drill down the use-case to words which are specific enough such that they can't be broken down further (as per SoC) while still being directly relevant to your solution, they will usually correspond in some way to your classes.
It is difficult to give an example to this based on your question (it is too vague), but App isn't usually a type of object (because it can usually be broken down in features and aspects), while list item may be a type of object (a UI element representing one component of the model). The click event, going from your UI to your model, is in somewhat of a gray area: you may choose to represent it as an object (ex. an implementation of the Command pattern) if it is handled in a way specific to your application (i.e. lifecycle - triggering and consuming, not necessarily its implementation), but most of the times it is generic enough to be a language idiom.
Going further, there are several principles and stereotypes which people have identified as good practice when pursuing object-oriented design, which are actually the living definition of the concept. The theoretical basics are abstraction, encapsulation and polymorphism (another personal opinion: inheritance, is not a first-class citizen, for theoretical reasons - it is actually a kind of subtype polymorphism, and for practical reasons - I'm with the GoF here, favor composition). Consequently, when designing your objects, try to consider the application of these principles, because in an overwhelming majority of cases they will lead to what most people consider OOP.
A lot more can be derived starting from the above: unlike modules, objects are small and many (stricter observation of encapsulation and abstraction). Because they are so, the structural relationships between objects become more important, therefore one needs to consider design patterns more carefully than in modular design. Also, since objects have smaller, well defined areas of responsibility within the context of your solution, their life cycle will not usually coincide with the life cycle of your application, therefore, their creation and destruction becomes a design problem. Even more so, since you now have many objects covering the same responsibility as a large module, you really need to consider how they communicate while observing SoC, hence it is important to design with decoupled interface contracts, otherwise the objects will end up exposing too much of their state to their peers.
Programming languages supporting modern OOP will give you an even wider array of tools - which are themselves derived as implementations of the theoretical principles above: they will have features which support the basic "tenets" (ex. some form of interface, some form of enforcing encapsulation), features which separate vertical concerns (your solution's implementation, from abstract to specific) from horizontal concerns (aspects & policy applicable to all features - life cycle, object persistence), features reconciling the simplicity of linear control flow with the granularity of OOP design (exception handling, task parallelism, lambdas). Using correctly, and maybe even mastering a powerful language which was designed with OOP in mind (such as Java, C# or maybe even C++ - the latter with a lot of protest including from yours truly) is a great way to gain good insight into how to drive your designs.
Finally, OOP applied to the letter may indeed be too orthodox for practical purposes, therefore always consider the hows and whys (I think a good consensus between answers to this question will be to take everything with a grain of salt). OOP is a vehicle, not a purpose in itself, always put your solution's restrictions before theory - maybe even with a YAGNI approach.
Best Answer
Many of the OOP's performance problems come from indirection caused by inheritance and virtual methods. The virtual methods are problematic because:
If you remove this, you will loose major point of using OOP, like modularity or extensibility, but you will gain a performance. The major advantage of C++ (especially compared to Java and C#) is you can pick where you want this indirection and where you want non-OOP way of doing things. You could do this in C#, but it is not that nice and easy as in C++.