Cyclomatic Complexity measures the number of linear paths through a program. It claims that the more paths there are, the more complex your code is. In essence the more paths there are, the higher the possibility of bugs.
The most common mechanism to compute the cyclomatic complexity is by counting branches in the code, given that a branch defines a point in your code where program flow will potentially bifurcate depending on a condition. (nb. CCMetrics uses this technique).
Cyclomatic Complexity was really developed for procedural languages. Some attempts have been made to apply CC to object orientation, but for the most part this involves averaging out the complexity of the methods in the class to provide a class complexity metric.
But I think there are many more ways to encode complexity into object oriented code. Where as a simple if statement can generate two different paths of execution, what if the code made use of an object instance that was injected into the procedure or class? Polymorphism allows us to see any object in terms of a specific interface regardless of its implementation. Yet changes in the implementation can drastically impact the program flow.
We may assume that the object being called back will be audited as part of our complexity analysis, but there is no guarantee of that. By definition an interface can be implemented by *any* object. What's more we may never know the exact combinations of objects being passed in, and what their dependencies are and so on. It's quite clear that using polymorphism dramatically increases the possible states in your application, and this has a direct impact on the program's complexity.
It's easy to think that seemingly elegant OOP solutions can actually reduce complexity. I recently read of a design pattern (the State Pattern) that, among other things, promotes the use of polymorphism in order to reduce the number of branches in the code. However given the choice between a simple if statement versus calling into a potentially unknown object, the less complex solution may well be the simple if statement.
The bottom line is that OOP complexity auditing techniques need more study. Cyclomatic complexity is fairly useful when limited to the scope of a single method, but has less use when looking at the complexity of an entire class hierarchy.
I think we need more metrics for determining the complexity of object oriented applications, especially one that takes aspects such as polymorphism, coupling and cohesion into account. If you know of any good papers on the topic, please leave a comment.