- What happens when all three source files are used to build the program?
Answer: worker.cpp fails to compile because declarations from main.cpp are not visible in its translation unit.
When building a C++ program, each source file is compiled independently as its own translation unit. This means that what you #include in one .cpp file has absolutely no effect on any other .cpp file — declarations do not "spread" between source files at compile time.
Here's the key: before the compiler can generate code for a function call, it must have seen a declaration of that function within the same translation unit. In worker.cpp, transform is called but never declared — no #include "api.h", no forward declaration, nothing. The compiler processing worker.cpp has no knowledge that transform even exists, so it raises a compile error. That makes A the correct answer.
Looking at the wrong choices: B describes a linker error based on the false idea that every translation unit needs its own definition of transform — that's backwards. Definitions belong in one place; it's declarations that each translation unit needs. C is the most tempting trap: it implies that main.cpp including api.h somehow makes the declaration available to worker.cpp. This is simply not how compilation works — the linker connects object files after compilation, but it cannot retroactively supply declarations to a file that already failed to compile. D is entirely fictional; C++ explicitly allows and requires you to declare a function before defining it, so including a header before a definition is standard practice.
Study tip: Burn this rule into memory — each translation unit is an island. Every .cpp file must independently declare everything it uses, typically via #include. Linker visibility and compiler visibility are completely separate concerns.
- After the two source files are linked, which behavior follows from this organization?
Answer: Each function updates a different nextId because the namespace-scope static object has internal linkage.
Whenever you see a question involving a variable declared at namespace scope in a header file, your first instinct should be to ask: what is its linkage? Linkage determines whether multiple translation units share one object or each get their own copy.
The keyword static at namespace scope gives a variable internal linkage, meaning each translation unit that includes the header gets its own independent copy of nextId, invisible to other translation units. So when alpha.cpp and beta.cpp both include ids.h, they each receive a private nextId initialized to 0. Incrementing one has absolutely no effect on the other. That makes D correct — the two functions operate on entirely separate variables.
A is wrong because include guards only prevent a single translation unit from seeing the same header twice during one compilation pass. They do nothing to unify objects across different translation units. There is no mechanism by which a header creates a "program-wide" object unless extern linkage is involved.
B describes what would happen if nextId were declared extern (external linkage) and defined in both translation units — the linker would see a duplicate symbol and error out. But static specifically prevents external linkage, so the linker never sees a conflict; both copies are translation-unit-private.
C invents a behavior that doesn't exist in C++. There's no "first included" rule that collapses two internal-linkage objects into one.
As a study tip: memorize the linkage table — static at namespace scope = internal, extern = external, no specifier for most variables = external. Linkage questions are a reliable exam staple.
- Why does this organization fail, and what is the most direct correction if
engine_ must remain a by-value member? Answer: Engine is incomplete when Car is defined, so Car.h must include the header that fully defines Engine.
When you see a question about class member declarations in C++, ask yourself: does the compiler have enough information at the point of declaration to know the size and layout of every member? For a by-value member like engine_, the compiler must know Engine's complete definition — its fields, size, everything — right where Car is defined, because it needs to allocate the correct space inside Car.
In Car.h, only a forward declaration class Engine; appears before Car's definition. A forward declaration tells the compiler that Engine exists as a type, but nothing more. That's sufficient for pointers or references (Engine*, Engine&), but not for a by-value member. The compiler literally cannot compute sizeof(Car) without knowing sizeof(Engine). The fix is straightforward: replace the forward declaration in Car.h with #include "Engine.h", giving the compiler Engine's full definition wherever Car.h is included. That's why A is correct.
B confuses linkage with completeness. Linkage determines where a symbol is visible across translation units; it has nothing to do with whether a class definition is available to the compiler during parsing. Moving a definition into .cpp wouldn't help headers that include Car.h.
C is simply wrong — C++ absolutely allows user-defined types as class members; that's a foundational feature of the language.
D misidentifies the problem as a linker or compilation-order issue. This is a compile-time problem — the compiler rejects incomplete types for by-value members before linking ever begins.
Study tip: Memorize this rule — forward declarations enable pointers/references to a type; #include (full definition) is required for by-value members, inheritance, and calling member functions.
- Which statement best describes this program?
Answer: It is ill-formed because each translation unit contains a definition of the same non-inline external function.
When a question involves header files and linking, you need to think beyond preprocessing and focus on the One Definition Rule (ODR): in a C++ program, a non-inline function with external linkage may be defined only once across all translation units combined.
Here's what's happening. Each .cpp file is compiled independently. When first.cpp includes convert.h, it receives and compiles the full definition of convert. When second.cpp does the same, it also receives and compiles that same definition. Now the linker sees two object files, each exporting a definition of convert — a direct ODR violation. The program is ill-formed, making B correct.
A is wrong because it misunderstands what include guards do. Guards prevent a single translation unit from including the same header twice within itself. They have no effect across different translation units — they only operate during preprocessing of one file at a time.
C is wrong because preprocessing has no rule against function definitions inside guarded headers. The preprocessor only handles directives like #include and #ifdef; it doesn't evaluate whether a definition is legal. That judgment happens at the compilation and linking stages.
D is wrong because it inverts the ODR. Identical external definitions appearing in multiple translation units is precisely what the rule forbids. If you want a function usable across files, declare it in the header and define it in exactly one .cpp, or mark it inline, which explicitly allows one definition per translation unit.
A useful rule of thumb: headers should contain declarations, not definitions, unless the function is marked inline (or is a template).
- Which description of the compilation is correct?
Answer: The command creates two translation units, and common.h is processed separately as part of each source file.
When you see a question about compilation and header files, the key concept to anchor on is the translation unit — the fundamental unit of compilation in C++. A translation unit is a single source file after preprocessing, meaning after all #include directives have been expanded inline into that file.
When you run g++ -c alpha.cpp beta.cpp, the compiler processes each .cpp file independently and sequentially. Each file gets its own full preprocessing pass, producing its own translation unit. So alpha.cpp and beta.cpp each become a separate translation unit, giving you exactly two — which is what D describes. The include guard in common.h prevents the header from being included twice within the same translation unit, not from being included across different translation units. Each .o file is compiled in isolation; neither knows the other exists at this stage.
Answer A is wrong because listing multiple source files in one compiler command does not merge them. Each file is still preprocessed and compiled independently — they are not concatenated. Answer B reflects a common misconception about include guards. Guards use #ifndef/#define logic that resets per translation unit, so common.h is fully processed in both files, not just the first one listed. Answer C is wrong because included headers are not compiled as separate translation units — they are textually inserted into the including source file during preprocessing and compiled as part of it.
A good rule of thumb: one .cpp file = one translation unit. Include guards protect within a translation unit; they have no memory across separate compilation units.
- Which assessment is most accurate?
Answer: The program violates the one-definition rule because preprocessing produces different definitions of the same inline function.
When you see a question involving inline functions and conditional compilation across translation units, your first instinct should be to think about the One Definition Rule (ODR). The ODR requires that every inline function have an identical definition in every translation unit that uses it.
Here's the key insight: the C++ preprocessor runs before the compiler sees any code. When one.cpp includes limit.h with LARGE_LIMIT defined, preprocessing produces a function body that returns 100. When two.cpp includes the same header without that macro, preprocessing produces a body that returns 10. By the time the compiler and linker see these, the conditional directives are gone — what remains are two functions named limit() with completely different bodies. This is a textbook ODR violation, making C the correct answer.
A is wrong because it mischaracterizes what inline actually permits. The inline specifier allows the same definition to appear in multiple translation units (so the linker doesn't complain about duplicate symbols), but it absolutely does not permit different definitions. Relaxing the "one location" requirement is not the same as relaxing the "one definition" requirement.
B is wrong because linker behavior is an implementation detail, not a language guarantee. Even if a particular linker silently picks one version, the program's behavior is still undefined — you cannot rely on which definition "wins."
D is wrong because conditional compilation has no effect on linkage. The macros are resolved before linkage rules even apply; nothing in the C++ standard causes differing macro environments to automatically create separate internal functions.
Study tip: Remember that inline relaxes where a definition can appear, never how many distinct definitions are allowed. ODR violations involving macros are especially sneaky because the source looks identical.
- Which change most reliably removes the circular dependency while allowing both headers to compile independently?
Answer: Replace both includes with forward declarations and store pointers or references to the opposite class in both definitions.
When two headers each include the other, you get a circular dependency: whichever header is processed first will try to include the second, which tries to include the first again — and include guards stop the recursion, leaving one class undefined when the other needs it. The real fix is to break the dependency entirely, not manage the order of its explosion.
This is exactly what B does. A forward declaration (e.g., class A; at the top of B.h instead of #include "A.h") tells the compiler "this type exists" without requiring its full definition. You can legally declare pointers or references to an incomplete type, so class B { A* owner; }; compiles fine with just a forward declaration of A. With both headers using forward declarations and pointer/reference members, neither header includes the other, and each compiles independently. This is the canonical, reliable solution.
A is backwards — removing include guards makes circular inclusion worse, causing infinite recursive inclusion and a compiler crash or explosion of redefinition errors. Guards don't cause the problem; the mutual #include does.
C fails because the problem isn't include order — it's that B stores A by value, which requires a complete definition of A. No matter how you shuffle includes, you can't have both classes store each other by value; the size calculation would be infinitely recursive.
D is nonsensical. Include guards belong in headers precisely to prevent multiple-inclusion across all translation units. Moving them into a single source file provides no protection during independent compilation of either header.
As a study tip: whenever you see circular header dependencies in C++, immediately think forward declarations + pointers/references. That pairing is the standard idiom for breaking include cycles.
- Which organization correctly provides one shared object without defining it in every translation unit?
Answer: Place extern int requestCount; in counter.h, and place int requestCount = 0; in counter.cpp.
When you see a question about sharing a global variable across multiple translation units, think about the One Definition Rule (ODR): every variable must be defined exactly once across the entire program, but it can be declared (via extern) as many times as needed.
The cleanest pattern for sharing a global is to put a declaration in the header and a single definition in one .cpp file. That's exactly what C does — extern int requestCount; in counter.h tells both source files "this variable exists somewhere," and int requestCount = 0; in counter.cpp provides the one true definition with storage. Any translation unit that includes the header knows the variable's type and can use it, while only one object file actually owns the memory.
A is wrong because placing a plain definition (int requestCount = 0;) directly in a header causes that definition to appear in every translation unit that includes the header. This violates the ODR and produces a linker error about multiply-defined symbols.
B is subtly dangerous: static in a header gives each translation unit its own private copy of requestCount. The two source files would each see a separate variable, so changes in one file are invisible to the other — the opposite of sharing.
D combines two mistakes: extern int requestCount = 0; is actually a definition (an initializer overrides extern), so you'd end up with two definitions — one in the header (stamped into every .cpp) and one in counter.cpp — again violating the ODR.
A handy rule of thumb: **headers declare, .cpp files define**. When you need one shared object, put extern in the header and the real definition in exactly one source file.
- What is the result of this arrangement?
Answer: The link fails because the unnamed-namespace function has internal linkage and does not define the external function declared in app.cpp.
Whenever you see a question involving unnamed (anonymous) namespaces in C++, your first instinct should be to think about linkage. Linkage determines whether a symbol defined in one translation unit is visible to another.
A function defined inside an unnamed namespace has internal linkage — it is invisible outside its own translation unit, as if it were declared static. When library.cpp is compiled, normalize exists only within that object file's private scope. No other translation unit can "see" or reference it by name. When the linker processes app.cpp, it finds extern int normalize(int), which declares a symbol with external linkage — something that must be resolved across translation units. Because the unnamed-namespace version of normalize never exports an external symbol, the linker finds nothing to satisfy app.cpp's declaration, and the link fails. That makes B correct.
A is wrong because extern does not magically pierce internal linkage. It tells the linker "find this symbol somewhere else," but internal-linkage symbols are invisible to that search by definition.
C is wrong because unnamed namespaces can absolutely contain function definitions — they are a standard C++ mechanism for giving functions internal linkage without using static.
D is wrong because link order can affect which definition wins when multiple external symbols with the same name exist (a separate issue), but it cannot make an internal-linkage symbol externally visible regardless of order.
Study tip: Treat unnamed namespaces as the modern replacement for file-static. Any time you see one, immediately flag the symbols inside as having internal linkage — they can never satisfy extern declarations in other files.
- Which change most directly satisfies the requirement?
Answer: Mark the header definition inline and keep the definition identical in every translation unit.
When a function definition lives in a header included by multiple source files, the linker sees that definition in every translation unit. Normally, this violates the One Definition Rule (ODR), causing a "multiple definition" linker error. The key concept here is understanding which storage-class or linkage specifier resolves this conflict while preserving external linkage.
The inline keyword — answer A — is the correct tool. Marking a function inline tells the compiler and linker that multiple identical definitions may exist across translation units, and the linker should merge them into a single externally linked entity. This is exactly the requirement: one shared function, defined in the header, usable everywhere.
Answer B is wrong because extern on a function definition doesn't suppress the ODR violation — it simply makes external linkage explicit, which functions already have by default. You'd still get a linker error from duplicate definitions.
Answer C is the most dangerous distractor. static does suppress the linker error, but it gives each translation unit its own private copy of the function with internal linkage — the exact opposite of "one externally linked entity." Every .cpp file gets its own version, which wastes code size and breaks the design requirement.
Answer D is a misconception about include guards. Guards prevent a header from being included twice within the same translation unit, not from being compiled into multiple translation units. The linker still sees multiple definitions.
Study tip: Remember the pairing — inline = "many identical definitions, one logical entity with external linkage." static = "one definition per translation unit, internally linked." These two are frequently confused on C++ exams.