When creating a class library in C++, you can choose between dynamic (
.so) and static (
.a) libraries. What is the difference between them and when is it appropriate to use which?
Static libraries increase the size of the code in your binary. They're always loaded and whatever version of the code you compiled with is the version of the code that will run.
Dynamic libraries are stored and versioned separately. It's possible for a version of the dynamic library to be loaded that wasn't the original one that shipped with your code if the update is considered binary compatible with the original version.
Additionally dynamic libraries aren't necessarily loaded -- they're usually loaded when first called -- and can be shared among components that use the same library (multiple data loads, one code load).
Dynamic libraries were considered to be the better approach most of the time, but originally they had a major flaw (google DLL hell), which has all but been eliminated by more recent Windows OSes (Windows XP in particular).
Others have adequately explained what a static library is, but I'd like to point out some of the caveats of using static libraries, at least on Windows:
Singletons: If something needs to be global/static and unique, be very careful about putting it in a static library. If multiple DLLs are linked against that static library they will each get their own copy of the singleton. However, if your application is a single EXE with no custom DLLs, this may not be a problem.
Unreferenced code removal: When you link against a static library, only the parts of the static library that are referenced by your DLL/EXE will get linked into your DLL/EXE.
For example, if
b.obj and your DLL/EXE only references functions or variables from
a.obj, the entirety of
b.obj will get discarded by the linker. If
b.obj contains global/static objects, their constructors and destructors will not get executed. If those constructors/destructors have side effects, you may be disappointed by their absence.
Likewise, if the static library contains special entrypoints you may need to take care that they are actually included. An example of this in embedded programming (okay, not Windows) would be an interrupt handler that is marked as being at a specific address. You also need to mark the interrupt handler as an entrypoint to make sure it doesn't get discarded.
Another consequence of this is that a static library may contain object files that are completely unusable due to unresolved references, but it won't cause a linker error until you reference a function or variable from those object files. This may happen long after the library is written.
Debug symbols: You may want a separate PDB for each static library, or you may want the debug symbols to be placed in the object files so that they get rolled into the PDB for the DLL/EXE. The Visual C++ documentation explains the necessary options.
RTTI: You may end up with multiple
type_info objects for the same class if you link a single static library into multiple DLLs. If your program assumes that
type_info is "singleton" data and uses
type_info::before(), you may get undesirable and surprising results.