C++ 선언 vs 정의: 호출에 본문이 꼭 위에 있어야 할까? (Tour 3.1)

Short answer: In C++, a declaration informs the compiler of a name and type to enable calling, while a definition provides the actual implementation body, achieving the separation of interface and implementation.

This post follows the A Tour of C++ 3.1 Introduction study notes. It does not cover the details of headers or modules from 3.2 and focuses only on the basic concepts of declaration and definition.

What’s the difference between a declaration and a definition?

Short answer: A declaration announces the minimal interface needed to use a function — its name and type — while a definition implements the actual body that runs.

A C++ program consists of a great many independently developed parts: functions, user-defined types, class hierarchies, templates, and more. What matters most in this structure is clearly defining how these parts interact, and the most fundamental principle behind that is the separation of interface and implementation.

A declaration tells the compiler the minimal information needed to use a function or type — its name, parameter types, and return type. A definition, by contrast, contains the actual executable body inside braces ({ }), or the concrete implementation of a class member. Looking only at the interface part of the study notes’ example:

// Interface (declaration)
double calculate_tax(double amount, double rate);
double square(double x);

class Rectangle {
public:
    Rectangle(double w, double h);
    double area() const;
private:
    double width;
    double height;
};

At this point, only the parameter types, return types, and the list of class members are known — the actual calculation logic or constructor body doesn’t exist anywhere yet. Even so, this information alone is enough for the compiler to check any calling code that comes later.

relationship between declaration and definition

relationship between declaration and definition

Does the definition need to come before you can use a function?

Short answer: No. As long as the compiler sees the declaration (interface) first, it can check the arguments and compile the calling code normally.

The full body (definition) doesn’t need to appear above the code that calls it. As long as a declaration announcing the name, parameter types, and return type is visible first, the compiler can check at compile time whether the arguments passed at the call site match in count and type. Here is code that uses the calculate_tax, square, and Rectangle declared above, exactly as they were declared:

int main() {
    Rectangle rect{10.0, 5.0};
    std::cout << "Area: " << rect.area() << '\n';
    std::cout << "Tax: " << calculate_tax(100.0, 0.1) << '\n';
    std::cout << "square(4.0) = " << square(4.0) << '\n';
}

// Implementation (definition) — fine even below main()
double calculate_tax(double amount, double rate) {
    return amount * rate;
}
double square(double x) {
    return x * x;
}
Rectangle::Rectangle(double w, double h) : width{w}, height{h} {}
double Rectangle::area() const { return width * height; }

At the point where main() calls calculate_tax, square, and Rectangle::area, none of their definitions have appeared anywhere in the code yet. Because the declarations shown earlier already existed, the compiler has no trouble compiling the call site, and the definitions are free to live further down the file or even in a separate source file.

compiling a call from a declaration alone

compiling a call from a declaration alone

What maintenance benefit comes from separating interface and implementation?

Short answer: As long as the interface (declaration) stays the same, calling code never needs to change even if the internal implementation (definition) changes or gets optimized.

A caller doesn’t need to know how calculate_tax or Rectangle::area compute their results internally — the name, parameter types, and return type in the declaration are enough to write calling code. If the implementation later changes its logic or is optimized for performance, calling code doesn’t need to be touched as long as the declaration stays the same.

This separation is also what makes independent compilation of each part possible, which in turn improves maintainability. The specific mechanics of sharing declarations across files through headers or modules (section 3.2) are outside the scope of this post and are not covered here.

FAQ

Q. Does the entire implementation body always need to appear before the code that calls it?

A. No. Only the declaration needs to be visible before the call. The definition can reside further down or in a separate file.

Q. Are “declaration” and “interface” used to mean the same thing in C++?

A. Yes, in the context of Chapter 3.1, a declaration acts as the interface, providing the minimal information needed to use a function or type.

Sources

C++ study notes — 3.1 Introduction (A Tour of C++)