Before I begin describing class diagrams, I would like to bring out an important subtlety in the way people use them. This subtlety is usually undocumented but has an impact on the way you should interpret a diagram, for it very much concerns what it is you are describing with a model.
Following the lead of Steve Cook and John Daniels (1994), I say that there are three perspectives you can use in drawing class diagrams or indeed any model, but this breakdown is most noticeable in connection with class diagrams.
If you take the conceptual perspective, you draw a diagram that represents the concepts in the domain under study. These concepts will naturally relate to the classes that implement them, but there is often no direct mapping. Indeed, a conceptual model should be drawn with little or no regard for the software that might implement it, so it can be considered language-independent. (Cook and Daniels call this the essential perspective.)
Now we are looking at software, but we are looking at the interfaces of the software, not the implementation. Object-oriented development puts a great emphasis on the difference between interface and implementation, but this is often overlooked in practice because the notion of class in an OO language combines both interface and implementation. This is a shame, because the key to effective OO programming is to program to a class's interface rather than to its implementation. There is a good discussion of this in the first chapter of Gamma, Helm, Johnson, and Vlissides (1995). You often hear the word "type" used to talk about an interface of a class; a type can have many classes that implement it, and a class can implement many types.
In this view, we really do have classes and we are laying the implementation bare. This is probably the perspective used most often, but in many ways the specification perspective is often a better one to take.
Understanding perspective is crucial to both drawing and reading class diagrams. Unfortunately, the lines between the perspectives are not sharp, and most modelers do not take care to get their perspective sorted out when they are drawing. Although I've found that this often does not matter too much between the conceptual perspective and the specification perspective, it is very important to separate the specification perspective and the implementation perspective.
As I talk about class diagrams further, I will stress how each element of the technique depends heavily on the perspective.
Perspective is not part of the formal UML, but I have found it extremely valuable when modeling and when reviewing models. The UML can be used with all three perspectives. By tagging classes with a stereotype (see page 79), you can provide an indication of the perspective. You mark classes with <<implementation class>> to show the implementation perspective, and with <<type>> for the specification and conceptual perspectives.