Two terms that are often confused are subtyping and subclassing. This confusion is unsurprising, as many languages (CeePlusPlus, JavaLanguage, etc.) equate the two (more or less) - in C++, the only way to create a subtype is through subclassing. As a result, many ObjectOriented texts also treat them as equivalent or gloss over the differences. But they are two different concepts, neither of which need imply the other.
In short, subtyping is a mathematical concept having to do with substitutability, whereas subclassing is a type construction method found in most ObjectOrientedLanguages (if not all).
Subtyping
Subtyping is a mathematical relationship, ultimately related to sets. It is convenient to define a type as a set of possible values or states that an object may assume (for mutable objects, the object may transition between any value or state in the set; though not necessarily so). A subtype is, in this view, a subset and a proper subtype is a proper subset. This is known as SemanticSubtyping. This explanation is an oversimplification, but it will do.
Most modern OO languages use SyntacticSubtyping?, where types and subtypes are specified by construction. Syntactic subtyping is less powerful than semantic subtyping in that some types are difficult or impossible to create (depending on the features of the specific language). However, it's much easier to implement, and less likely to diverge. Syntactic subtyping also avoids many paradox issues that plague set-theoretic approaches - metaclasses and the like are difficult to model in SemanticSubtyping.
Some languages use a weaker approach still - nominative subtyping, wherein type/subtype relationships have to be explicitly declared, e.g., with extends clauses. CeePlusPlus and JavaLanguage are in this camp. Other languages provide structural subtyping, commonly known as DuckTyping, in which the subtype relationship is determined by feature comparison. (SmalltalkLanguage is in this category). However, all syntactic approaches still uphold the fundamental relationship of subtypes - they correspond to subsets. Substitutability still applies (up to a point; any language can allow a derived class method to do something nasty and predictable like dump core; no typechecker can deal with this).
Some of you may be asking "what about abstract base classes, or interfaces? Those don't have instances! How can a non-empty set be a subtype of the empty set?" Stay tuned.
Subclassing
Subclassing (also known as inheritance) is a method of class/object construction, wherein portions of one class or object are copied into another (with some of the copied features possibly being modified, or overridden, in the new class). In many languages, this technique is equivalent to subtyping - if class B inherits from class A, then by definition B is a subtype of the type A. Conversely, many languages don't provide any other means of creating subtypes other than subclassing. Languages in this camp include CeePlusPlus, JavaLanguage, and EiffelLanguage (though C++ does provide PrivateInheritance, which creates subclasses without subtyping - this feature is rarely used. Implementation of a JavaInterface is considered subclassing for this discussion).
There are many other ways of forming subtypes found in various languages:
At any rate... in languages where subtyping and subclassing are equivalent, there still is an important difference between the two. Suppose I have a base class Base, and two derived classes Derived1 and Derived2. (Assume Base has no other subclasses, direct or indirect - we're discussing nominatively typed languages like CeePlusPlus or JavaLanguage). There are several sets we can consider.
See the influential paper InheritanceIsNotSubtyping