A Tour of C++ 3장
모듈성에 관한
1. 인터페이스로 쓰이는 선언과 구현으로 쓰이는 정의를 구분한다.
// add.h
int add(int a, int b); // 선언만 포함
#include "add.h"
int add(int a, int b) {
return a + b; // 구현은 .cpp에 위치
}
헤더 파일과 소스 파일을 분리시켜 빌드 속도를 개선하고 재사용성을 높이자
2. module이 지원되는 헤더보다는 module이 낫다.
export module add;
export int add(int a, int b) {
return a + b;
}
모듈 사용을 통해 불필요한 매크로, include 중복을 제거해 빌드 성능을 높인다
3. 헤더 파일로 인터페이스를 표현해 논리적 구조를 강조한다.
// logger.h (인터페이스)
#ifndef LOGGER_H
#define LOGGER_H
class Logger {
public:
static void log(const std::string& message);
};
#endif
// logger.cpp (구현)
#include "logger.h"
#include <iostream>
void Logger::log(const std::string& message) {
std::cout << message << std::endl;
}
4. 함수를 구현한 소스 파일에 헤더를 #include 한다.
: 1과 비슷
5. 인라인이 아닌 함수 정의는 헤더에 쓰지 않는다.
#ifndef MYFUNCTIONS_H
#define MYFUNCTIONS_H
// 함수 선언: 인터페이스만 제공
void foo();
// 인라인 함수는 헤더에 정의해도 됨
inline void bar() {
// 인라인 함수 구현
}
#endif // MYFUNCTIONS_H
6. 네임 스페이스로 논리적 구조를 표현한다.
#ifndef MYLIBRARY_H
#define MYLIBRARY_H
namespace MyLibrary {
// 함수 선언
void foo();
// 클래스 선언
class Bar {
public:
void doSomething();
};
}
#endif // MYLIBRARY_H
#include <iostream>
#include "MyLibrary.h"
namespace MyLibrary {
// 함수 정의
void foo() {
std::cout << "MyLibrary::foo() 호출" << std::endl;
}
// 클래스의 멤버 함수 정의
void Bar::doSomething() {
std::cout << "MyLibrary::Bar::doSomething() 호출" << std::endl;
}
}
#include "MyLibrary.h"
int main() {
// 네임스페이스를 이용한 함수와 클래스 사용
MyLibrary::foo();
MyLibrary::Bar bar;
bar.doSomething();
return 0;
}
7. using 디렉티브는 전이나 기초 라이브러리에 사용하거나 지역 범위 안에 사용한다.
#include <iostream>
namespace A {
void foo() {
std::cout << "A::foo() 호출" << std::endl;
}
}
namespace B {
void foo() {
std::cout << "B::foo() 호출" << std::endl;
}
}
// 전역 범위에서 두 네임스페이스 모두의 이름을 가져옴
using namespace A;
using namespace B;
int main() {
foo(); // 이름 충돌로 인한 모호성(ambiguous call)
return 0;
}
8. using 디렉티브를 헤더 파일에 넣지 않는다.
-> 해당 헤더파일을 사용하면 using도 같이 사용되므로 혼란이 유발됨
9. 작은 값은 값으로, 큰 값은 참조로 전달한다.
-> 기본 자료형의 경우 크기가 작고 복사 비용이 낮지만, 크기가 큰 객체는 값으로 전달 시 오버헤드가 발생한다.
따라서 참조 등으로 복사하는 것이 효율적이다.
10. 그냥 참조로 전달하기보다는 const 참조로 전달하는 편이 낫다.
-> const 사용 시 readonly라는 것을 명확히 전달할 수 있고, 실수를 막을 수 있다.
11. 값을 인수로 내보내지 말고 함수 반환값으로 반환한다.
#include <iostream>
// 결과를 출력 인수로 전달 (비권장)
void calculateSum(int a, int b, int& result) {
result = a + b;
}
int main() {
int sum = 0;
calculateSum(3, 4, sum);
std::cout << "Sum: " << sum << std::endl;
return 0;
}
#include <iostream>
// 결과를 함수의 반환값으로 전달 (권장)
int calculateSum(int a, int b) {
return a + b;
}
int main() {
int sum = calculateSum(3, 4);
std::cout << "Sum: " << sum << std::endl;
return 0;
}
12. 반환 타입 추론을 남용하지 말자.
13. 구조적 바인딩을 남용하지 말자. 반환 타입을 명명한 코드가 대개 더 읽기 쉽다.
'C, C++ > C++ 여행' 카테고리의 다른 글
| [A Tour of C++] 7장 - 템플릿 (1) | 2025.06.10 |
|---|---|
| [A Tour of C++] 6장 - 필수 연산 (1) | 2025.05.17 |
| [A Tour of C++] 5장 - 클래스 (0) | 2025.05.14 |
| C++ 여행 조언 새기기 4 (0) | 2025.02.22 |
| C++ 여행 조언 새기기 2장 (0) | 2025.02.16 |