<p>There are two schools of thought on how to best extend, enhance, and reuse code in an object-oriented system:</p>

<ol>
<li><p>Inheritance: extend the functionality of a class by creating a subclass. Override superclass members in the subclasses to provide new functionality. Make methods abstract/virtual to force subclasses to "fill-in-the-blanks" when the superclass wants a particular interface but is agnostic about its implementation.</p></li>
<li><p>Aggregation: create new functionality by taking other classes and combining them into a new class. Attach an common interface to this new class for interoperability with other code.</p></li>
</ol>

<p>What are the benefits, costs, and consequences of each? Are there other alternatives?</p>

<p>I see this debate come up on a regular basis, but I don't think it's been asked on 
Stack Overflow yet (though there is some related discussion). There's also a surprising lack of good Google results for it. </p>

The difference is typically expressed as the difference between "is a" and "has a". Inheritance, the "is a" relationship, is summed up nicely in the
Liskov Substitution Principle
. Aggregation, the "has a" relationship, is just that - it shows that the aggregating object
has
one of the aggregated objects.
Further distinctions exist as well - private inheritance in C++ indicates a "is implemented in terms of" relationship, which can also be modeled by the aggregation of (non-exposed) member objects as well.