1학년 대학 수업/C++ 프로그래밍

11주차 복습 과제

hawon6691 2025. 11. 13. 15:47
728x90

C++, Java, C#, Kotlin, Swift, TypeScript 등은 명시적으로 지원하며, 일부 언어는 간접적으로 구현 가능합니다.


🧠 함수 오버로딩을 명시적으로 지원하는 언어들

이들 언어는 컴파일러 수준에서 함수 이름은 같지만 매개변수의 타입이나 개수가 다른 함수를 구분할 수 있도록 설계되어 있습니다:

  • C++: 함수 오버로딩의 대표적인 예. 매개변수 타입이나 개수로 구분.
  • Java: 클래스 내에서 같은 이름의 메서드를 여러 개 정의 가능.
  • C#: 메서드 오버로딩을 통해 다양한 시그니처를 지원.
  • Kotlin: 함수 이름은 같되 매개변수로 구분하는 오버로딩 지원.
  • Swift: 타입과 개수에 따라 함수 오버로딩 가능.
  • TypeScript: 함수 시그니처를 명시적으로 선언하여 오버로딩 구현 가능.
  • Ada: 오래된 언어지만 함수 오버로딩을 지원함.

⚙️ 함수 오버로딩을 간접적으로 구현 가능한 언어들

이들 언어는 기본적으로 오버로딩을 지원하지 않지만, 내부 로직으로 유사한 기능을 구현할 수 있습니다:

  • Python: 기본적으로 오버로딩을 지원하지 않지만, *args, **kwargs, 데코레이터 등을 활용해 유사 기능 구현 가능.
  • JavaScript: 동적 타입 언어로 오버로딩은 없지만, 매개변수 개수나 타입을 조건문으로 처리하여 유사하게 구현 가능.
  • PHP: 명시적 오버로딩은 없지만, 기본값 인수나 가변 인수를 통해 유사한 동작 가능.

❌ 함수 오버로딩을 지원하지 않는 언어

  • C: 함수 이름이 동일한 경우 컴파일 오류 발생. 함수 오버로딩은 지원하지 않음.

 

 

물론이죠! 아래는 함수 오버로딩을 명시적으로 또는 간접적으로 지원하는 여러 언어들의 예시입니다. 각 언어에서 같은 함수 이름을 사용하되 매개변수의 타입이나 개수에 따라 다르게 동작하는 방식입니다.


🧪 C++ 예시

#include <iostream>
using namespace std;

void print(int i) {
    cout << "정수: " << i << endl;
}

void print(double d) {
    cout << "실수: " << d << endl;
}

void print(string s) {
    cout << "문자열: " << s << endl;
}

int main() {
    print(10);
    print(3.14);
    print("Hello");
    return 0;
}

☕ Java 예시

public class OverloadExample {
    void greet(String name) {
        System.out.println("Hello, " + name);
    }

    void greet(String name, int age) {
        System.out.println("Hello, " + name + ". You are " + age + " years old.");
    }

    public static void main(String[] args) {
        OverloadExample ex = new OverloadExample();
        ex.greet("Alice");
        ex.greet("Bob", 30);
    }
}

💻 C# 예시

using System;

class Program {
    static void Show(string message) {
        Console.WriteLine("Message: " + message);
    }

    static void Show(int number) {
        Console.WriteLine("Number: " + number);
    }

    static void Main() {
        Show("Hello");
        Show(42);
    }
}

🧬 Kotlin 예시

fun describe(value: Int) {
    println("정수: $value")
}

fun describe(value: String) {
    println("문자열: $value")
}

fun main() {
    describe(100)
    describe("Kotlin")
}

🍎 Swift 예시

func greet(name: String) {
    print("Hello, \(name)")
}

func greet(name: String, age: Int) {
    print("Hello, \(name). You are \(age) years old.")
}

greet(name: "Emma")
greet(name: "Liam", age: 25)

🧠 TypeScript 예시

function greet(name: string): void;
function greet(name: string, age: number): void;
function greet(name: string, age?: number): void {
    if (age !== undefined) {
        console.log(`Hello, ${name}. You are ${age} years old.`);
    } else {
        console.log(`Hello, ${name}`);
    }
}

greet("Alice");
greet("Bob", 30);

🐍 Python (간접 구현)

def greet(*args):
    if len(args) == 1:
        print(f"Hello, {args[0]}")
    elif len(args) == 2:
        print(f"Hello, {args[0]}. You are {args[1]} years old.")
    else:
        print("Invalid arguments")

greet("Alice")
greet("Bob", 30)

 

 

#include <iostream>
#include <string>

class Dog {
private:
	std::string name;
	int age;
public:
	Dog();
	~Dog();
	std::string getName() const;
	void setName(std::string name);
	int getAge() const;
	void setAge(int age);
};

Dog::Dog() {
	age = 0;
	name = "none";
}

Dog::~Dog() {
	std::cout << "Dog " << name << " is destroyed\n";
}

std::string Dog::getName() const
{
	return name;
}

void Dog::setName(std::string name)
{
	this->name = name;
}

int Dog::getAge() const
{
	return age;
}

void Dog::setAge(int age)
{
	this->age = age;
}

int main()
{
	Dog coco;
	coco.setAge(1);
	coco.setName("Coco");
	std::cout << coco.getAge() << "\n";
	return 0;
}

 

이 C++ 코드는 Dog라는 클래스를 정의하고, 객체를 생성하여 이름과 나이를 설정한 뒤 출력하는 간단한 예제입니다. 각 부분을 자세히 설명드릴게요.


🐶 클래스 정의: Dog

class Dog {
private:
    std::string name;
    int age;
public:
    Dog();                      // 기본 생성자
    ~Dog();                     // 소멸자
    std::string getName() const;
    void setName(std::string name);
    int getAge() const;
    void setAge(int age);
};
  • 멤버 변수
    • name: 강아지의 이름 (문자열)
    • age: 강아지의 나이 (정수)
  • 생성자 (Dog())
    • 객체가 생성될 때 자동으로 호출됨
    • name을 "none", age를 0으로 초기화
  • 소멸자 (~Dog())
    • 객체가 소멸될 때 호출됨
    • 콘솔에 "Dog [이름] is destroyed" 메시지 출력
  • Getter/Setter
    • getName(), getAge(): 현재 이름과 나이를 반환
    • setName(string), setAge(int): 이름과 나이를 설정

🧱 생성자 구현

Dog::Dog() {
    age = 0;
    name = "none";
}
  • Dog 객체가 생성될 때 기본값으로 초기화

🧹 소멸자 구현

Dog::~Dog() {
    std::cout << "Dog " << name << " is destroyed\n";
}
  • 객체가 메모리에서 해제될 때 호출됨
  • 디버깅이나 리소스 해제 확인용으로 사용

🧪 메서드 구현

std::string Dog::getName() const { return name; }
void Dog::setName(std::string name) { this->name = name; }

int Dog::getAge() const { return age; }
void Dog::setAge(int age) { this->age = age; }
  • const 키워드는 해당 메서드가 멤버 변수를 변경하지 않음을 보장

🧾 main() 함수

int main() {
    Dog coco;
    coco.setAge(1);
    coco.setName("Coco");
    std::cout << coco.getAge() << "\n";
    return 0;
}
  • Dog 객체 coco를 생성
  • setAge(1), setName("Coco")로 속성 설정
  • getAge()로 나이를 출력 → 1 출력
  • 프로그램 종료 시 coco 객체가 소멸되며 소멸자 호출 → "Dog Coco is destroyed" 출력

🧵 실행 결과

1
Dog Coco is destroyed

 

C++에서 생성자에서 멤버 변수에 초기값을 지정하는 이유

 

좋은 질문이에요! C++에서 생성자에서 멤버 변수에 초기값을 지정하는 이유는 객체가 생성될 때 안정적이고 예측 가능한 상태로 시작하도록 보장하기 위해서입니다. 아래에 그 이유를 자세히 설명할게요.


🧱 1. 초기화는 객체의 안정성을 보장한다

  • 생성된 객체가 의미 있는 값을 가지도록 하기 위해 초기값을 설정합니다.
  • 초기화하지 않으면 멤버 변수는 **쓰레기 값(garbage value)**를 가질 수 있어, 예기치 않은 동작이나 버그가 발생할 수 있습니다.
class Dog {
    int age; // 초기화하지 않으면 쓰레기 값
public:
    Dog() {
        age = 0; // 안정적인 초기값
    }
};

🧠 2. 초기화 리스트를 사용하면 성능과 명확성이 향상된다

Dog::Dog() : age(0), name("none") {}
  • 초기화 리스트는 생성자 본문보다 더 빠르고 효율적입니다.
  • 특히 const 멤버참조형 멤버는 반드시 초기화 리스트로 초기화해야 합니다.

🧪 3. 클래스의 일관성을 유지한다

  • 모든 객체가 생성될 때 동일한 초기 상태를 갖도록 하면, 디버깅과 유지보수가 쉬워집니다.
  • 예를 들어, Dog 클래스의 모든 객체가 age = 0, name = "none"으로 시작하면 예측 가능한 동작을 합니다.

🔐 4. 보안과 안정성 측면에서도 중요

  • 초기화되지 않은 변수는 보안 취약점을 유발할 수 있습니다.
  • 민감한 데이터를 다루는 경우, 초기화는 필수입니다.

✨ 요약

이유 설명

안정성 쓰레기 값 방지, 예측 가능한 상태
성능 초기화 리스트는 효율적
일관성 모든 객체가 동일한 초기 상태
보안 초기화되지 않은 변수는 위험

 

물론입니다! 아래는 주어진 C++ 코드를 Java로 변환한 예입니다. Java에서는 소멸자(~Dog)가 없고, 대신 가비지 컬렉션이 자동으로 메모리를 관리합니다. System.out.println()을 사용해 콘솔 출력도 처리합니다.


🐾 Java 버전: Dog.java

public class Dog {
    private String name;
    private int age;

    // 생성자
    public Dog() {
        this.name = "none";
        this.age = 0;
    }

    // 소멸자 대신 finalize() (권장되진 않음, 예시용)
    @Override
    protected void finalize() throws Throwable {
        System.out.println("Dog " + name + " is destroyed");
        super.finalize();
    }

    // Getter
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    // Setter
    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    // main 메서드
    public static void main(String[] args) {
        Dog coco = new Dog();
        coco.setAge(1);
        coco.setName("Coco");
        System.out.println(coco.getAge());
    }
}

🔍 주요 차이점 요약

항목  C++  Java
소멸자 ~Dog() finalize() (사용 권장 X)
출력 std::cout System.out.println
문자열 std::string String
접근 제어 private, public 동일
객체 생성 Dog coco; Dog coco = new Dog(); (Java에서는 new 생략 가능할 때도 있음)

Java에서는 finalize()는 더 이상 권장되지 않으며, 대신 명시적인 자원 해제가 필요한 경우 try-with-resources나 AutoCloseable을 사용하는 것이 좋습니다. 위 예시는 C++의 소멸자 동작을 흉내내기 위한 참고용입니다.

 

물론이죠! 아래는 주어진 C++ 코드를 **C#**으로 변환한 예입니다. C#은 Java와 유사한 구조를 가지며, 클래스 정의, 생성자, 속성 설정 등이 직관적으로 표현됩니다.


🐾 C# 버전: Dog.cs

using System;

public class Dog
{
    private string name;
    private int age;

    // 생성자
    public Dog()
    {
        name = "none";
        age = 0;
    }

    // 소멸자 (C#에서는 거의 사용되지 않음, 예시용)
    ~Dog()
    {
        Console.WriteLine($"Dog {name} is destroyed");
    }

    // Getter
    public string GetName()
    {
        return name;
    }

    public int GetAge()
    {
        return age;
    }

    // Setter
    public void SetName(string name)
    {
        this.name = name;
    }

    public void SetAge(int age)
    {
        this.age = age;
    }

    // Main 메서드
    public static void Main()
    {
        Dog coco = new Dog();
        coco.SetAge(1);
        coco.SetName("Coco");
        Console.WriteLine(coco.GetAge());
    }
}

🔍 주요 차이점 요약

항목 C++ C#

소멸자 ~Dog() ~Dog() (거의 사용되지 않음)
출력 std::cout Console.WriteLine
문자열 std::string string
접근 제어 private, public 동일
객체 생성 Dog coco; Dog coco = new Dog();

C#에서는 ~Dog() 소멸자는 가비지 컬렉터가 호출할 때 실행되며, 직접 호출하거나 예측하기 어렵기 때문에 일반적으로는 IDisposable 인터페이스와 Dispose() 메서드를 사용하는 방식이 더 선호됩니다.

 

C++에서 **생성자 함수 중첩(Constructor Overloading)**은 같은 클래스 안에 여러 개의 생성자를 정의하여, 객체를 생성할 때 다양한 방식으로 초기화할 수 있도록 하는 기능입니다. 이는 **함수 오버로딩(Function Overloading)**의 일종으로, 생성자의 매개변수 개수나 타입이 다르면 여러 생성자를 정의할 수 있습니다.


🧱 기본 구조

class MyClass {
private:
    int x;
    std::string name;

public:
    MyClass();                         // 기본 생성자
    MyClass(int value);                // 정수 하나 받는 생성자
    MyClass(int value, std::string n); // 정수와 문자열 받는 생성자
};

🧪 예제: 생성자 중첩 사용

#include <iostream>
#include <string>

class Dog {
private:
    std::string name;
    int age;

public:
    Dog() {
        name = "none";
        age = 0;
    }

    Dog(std::string name) {
        this->name = name;
        age = 0;
    }

    Dog(std::string name, int age) {
        this->name = name;
        this->age = age;
    }

    void info() {
        std::cout << "Name: " << name << ", Age: " << age << "\n";
    }
};

int main() {
    Dog d1;                        // 기본 생성자
    Dog d2("Coco");                // 이름만 설정
    Dog d3("Max", 3);              // 이름과 나이 설정

    d1.info();  // Name: none, Age: 0
    d2.info();  // Name: Coco, Age: 0
    d3.info();  // Name: Max, Age: 3

    return 0;
}

🧠 생성자 중첩의 장점

  • 유연성: 다양한 방식으로 객체를 초기화할 수 있음
  • 가독성: 코드가 명확하고 직관적
  • 재사용성: 공통 초기화 로직을 다른 생성자에서 호출 가능

🔁 생성자 위임 (C++11 이상)

C++11부터는 **생성자끼리 호출(delegate)**할 수 있습니다:

class Dog {
private:
    std::string name;
    int age;

public:
    Dog() : Dog("none", 0) {} // 다른 생성자 호출

    Dog(std::string name) : Dog(name, 0) {}

    Dog(std::string name, int age) {
        this->name = name;
        this->age = age;
    }
};

이렇게 하면 중복 코드를 줄이고, 모든 생성자가 하나의 메인 생성자를 통해 초기화되므로 유지보수가 쉬워집니다.


함수 중첩 - function overloading

의 장점은 오로지 편의성이다.

개발자들이 여러번 함수를 만드는 것보다 자료형만 다르거나 비슷하게 작동하는 함수들을 전부 묶어서 관리하는 것이 가독성도 좋고 개발자들이 덜 신경이 쓰인다. 사실 가독성도 개발자들의 편의 때문이다.

예를 들어

C에서는

int add_i(int numA, int numB) { return numA + numB; }
float add_f(float numA, float numB) { return numA + numB; }
double add_d(double numA, double numB) { return numA + numB; }

다른 형태를 원한다면 다 따로따로 작성을 해야한다.

이런 코드가 1~2줄이면 사용을 할 필요가 없지만 이게 100줄, 1000줄을 코드들이 있는 상황에서 오버로딩을 사용하는 것이 효율적이다.

C++에서는

int add(int numA, int numB) { return numA + numB; }
float add(float numA, float numB) { return numA + numB; }
double add(double numA, double numB) { return numA + numB; }

이렇게 함수 이름을 같게 해서 하는 것이 가독성도 있고 사용하기 편하다.

재사용성, 가독성, 유지보수성 이런 말들은 사실은 다 편의성이다.

개발자들이 100줄을 작성할 것을 50줄로 바꿔주는 것이 재사용성, 가독성이다.

이야기하신 관점, 굉장히 흥미롭고 통찰력 있어요.

실제로 재사용성, 가독성, 유지보수성 같은 소프트웨어 설계 원칙들은 결국 개발자의 편의성과 생산성을 높이기 위한 도구들이죠.


🧠 "재사용성 = 편의성"이라는 관점

  • 재사용성은 "같은 기능을 반복해서 만들지 않아도 된다"는 뜻이죠.
  • → 즉, 코드를 덜 쓰고, 더 빠르게 개발할 수 있게 해줍니다.
  • 가독성은 "코드를 쉽게 읽고 이해할 수 있다"는 뜻인데,
  • → 결국 유지보수나 협업이 편해진다는 말이기도 해요.
  • 추상화, 캡슐화, 모듈화 같은 개념들도
  • → 전부 사람이 코드를 다루기 쉽게 만들기 위한 편의 장치라고 볼 수 있어요.

✨ 예를 들어 보면

// 재사용성 없는 코드
int sum1 = a1 + b1;
int sum2 = a2 + b2;
int sum3 = a3 + b3;

// 재사용성 있는 코드
int sum(int a, int b) { return a + b; }
int sum1 = sum(a1, b1);
int sum2 = sum(a2, b2);
int sum3 = sum(a3, b3);

  • 위처럼 함수로 추출하면 줄 수는 비슷해 보여도,의미가 명확해지고, 재사용이 가능해지고, 유지보수가 쉬워집니다.

🧩 결국 핵심은 "사람 중심"

컴퓨터는 100줄이든 1000줄이든 상관없어요.

하지만 사람은 읽고, 이해하고, 고쳐야 하니까

→ 줄 수를 줄이고, 의미를 명확히 하고, 중복을 제거하는 게 중요해지는 거죠.


💬 요약하면

재사용성, 가독성, 유지보수성… 결국 다 "사람이 편하자고 만든 개념"이다.

당신의 말처럼, 개발자가 100줄 쓸 걸 50줄로 줄이는 것,

그게 바로 편의성이고, 그 편의성을 실현하는 도구가 재사용성과 가독성이에요.


혹시 이 주제로 더 깊이 들어가서 "좋은 코드란 무엇인가?" 같은 철학적인 얘기도 해볼까요? 😄

🧠 “좋은 코드란 없다”는 말의 진짜 의미

  • 재사용성만 추구하면 → 지나치게 추상화되어 이해하기 어려운 코드가 되고
  • 가독성만 추구하면 → 중복이 많아지고 유지보수가 어려워지고
  • 유지보수성만 추구하면 → 미래를 너무 의식한 설계로 현재가 복잡해지고…

결국 모든 소프트웨어 품질 속성은 서로 긴장 관계에 있어요.

하나를 극단적으로 추구하면 다른 하나가 희생되기 쉽죠.


⚖️ 그래서 “균형”이 핵심

좋은 코드는 절대적인 기준이 아니라, 상황에 맞는 균형의 산물이에요.

  • 팀의 규모, 개발자의 숙련도, 프로젝트의 수명, 배포 주기, 도메인 복잡도… 이런 요소들에 따라 “좋음”의 기준은 계속 바뀝니다.

💬 그래서 “좋은 코드란 없다”는 말은…

사실은 이렇게 바꿔 말할 수도 있어요:

“좋은 코드란, 언제나 맥락 속에서만 존재한다.”


✨ 당신의 말에 덧붙이자면

  • 좋은 코드를 쓰는 건 기술이 아니라 태도에 가까워요.
  • 치우치지 않으려는 노력, 균형을 감각적으로 잡으려는 감수성, 그게 결국 좋은 개발자를 만드는 거죠.

생성자는 중첩이 가능하지만 소멸자는 불가능하다.

결론부터 말하면: C++에서 생성자는 중첩(오버로딩)이 가능하지만, 소멸자는 중첩이 불가능합니다.


🧱 왜 생성자는 중첩이 가능할까?

  • 생성자는 함수처럼 매개변수의 개수나 타입이 다르면 여러 개 정의 가능합니다.
  • 이를 통해 다양한 방식으로 객체를 초기화할 수 있어요.
class Dog {
public:
    Dog();                      // 기본 생성자
    Dog(std::string name);      // 이름만 받는 생성자
    Dog(std::string name, int age); // 이름과 나이 받는 생성자
};


❌ 왜 소멸자는 중첩이 불가능할까?

  • C++에서 소멸자는 이름이 고정되어 있고, 매개변수를 가질 수 없습니다.
  • 즉, 클래스당 소멸자는 오직 하나만 정의할 수 있어요.
class Dog {
public:
    ~Dog(); // 매개변수 없음, 오버로딩 불가
};

  • 소멸자는 객체가 소멸될 때 자동 호출되므로, 인자를 전달할 수 없고, 오버로딩할 필요도 없습니다.

🔍 요약

항목  생성자  소멸자
이름 클래스 이름과 같음 ~클래스이름
오버로딩 가능 (매개변수 다르면 OK) 불가능 (매개변수 없음)
호출 시점 객체 생성 시 객체 소멸 시
목적 초기화 정리/해제

🧠 기본 개념

  • default parameter는 함수 선언 또는 정의에서 매개변수에 기본값을 지정하는 것
  • default argument는 함수 호출 시 인수를 생략하면 자동으로 사용되는 값

즉, 둘은 같은 개념을 다른 관점에서 부르는 말이에요.


✅ 기본 매개변수 예시

#include <iostream>
using namespace std;

void greet(string name = "Guest") {
    cout << "Hello, " << name << "!\\n";
}

int main() {
    greet();           // 인수 생략 → "Hello, Guest!"
    greet("Hawon");    // 인수 제공 → "Hello, Hawon!"
    return 0;
}

  • greet()는 인수를 생략했지만 "Guest"가 자동으로 들어갑니다.
  • greet("Hawon")은 기본값을 무시하고 직접 전달한 값을 사용합니다.

🧱 여러 개의 기본값

void printInfo(string name = "Unknown", int age = 0) {
    cout << name << " is " << age << " years old.\\n";
}

printInfo();                  // Unknown is 0 years old.
printInfo("Alice");           // Alice is 0 years old.
printInfo("Bob", 25);         // Bob is 25 years old.


⚠️ 주의할 점

  1. 기본값은 오른쪽에서 왼쪽으로만 지정 가능
  2. void test(int a = 1, int b); // ❌ 오류: 오른쪽에 기본값이 없으면 안 됨 void test(int a, int b = 2); // ✅ OK
  3. 기본값은 선언부에만 쓰는 것이 일반적
  4. // 헤더 파일 void greet(string name = "Guest"); // 소스 파일 void greet(string name) { ... } // 여기엔 기본값 쓰지 않음

✨ 요약

용어  의미
default parameter 함수 선언 시 매개변수에 기본값을 지정
default argument 함수 호출 시 생략된 인자에 자동으로 들어가는 값
장점 코드 간결성, 함수 재사용성 증가

생성자에 default parameter가 있다면, 일반 생성자를 따로 만들 필요가 없는 경우가 많습니다.

하지만 이건 상황에 따라 다릅니다. 아래에서 예시와 함께 설명드릴게요.


✅ 기본값이 있는 생성자 하나로 충분한 경우

class Dog {
private:
    std::string name;
    int age;

public:
    Dog(std::string name = "none", int age = 0) {
        this->name = name;
        this->age = age;
    }

    void info() {
        std::cout << name << " is " << age << " years old.\\n";
    }
};

int main() {
    Dog d1;               // 기본값 사용 → "none", 0
    Dog d2("Coco");       // age는 기본값 0
    Dog d3("Max", 3);     // name과 age 모두 지정
    d1.info();
    d2.info();
    d3.info();
}

  • 하나의 생성자만으로 기본 생성자, 부분 초기화, 전체 초기화를 모두 처리할 수 있어요.
  • 이게 바로 default parameter의 강력한 장점이죠.

⚠️ 하지만 일반 생성자를 따로 만드는 경우도 있음

1. 명확한 의도 표현

Dog() { std::cout << "Default dog created\\n"; }
Dog(std::string name, int age) { ... }

  • 기본 생성자에서만 특정 로직을 실행하고 싶을 때

2. 오버로딩 기반의 코드 분리

  • 각 생성자마다 다른 초기화 방식이나 검증 로직을 넣고 싶을 때

3. 템플릿이나 상속 구조에서 충돌 방지

  • 복잡한 클래스 계층에서는 명시적인 기본 생성자가 필요할 수 있어요

✨ 요약

 

상황 기본값 있는 생성자  하나로 충분?
단순한 클래스 ✅ 가능
초기화 방식이 다양함 ❌ 별도 생성자 필요
생성자마다 다른 로직 필요 ❌ 별도 생성자 필요
상속/템플릿 구조 복잡함 ❌ 명시적 생성자 필요

당신 말처럼, 기본값이 있다면 중복된 생성자는 줄일 수 있어요.

하지만 의도, 구조, 확장성에 따라 일부러 나누는 경우도 있다는 점이 핵심이에요.

default parameter, default argument를 잘 이용하면 함수 중첩도 더 줄일 수 있다.

100줄에 함수를 중첩(function overloading)을 이용하면 50줄이 될 수 있고 그 함수 중첩도 default parameter, default argument를 잘만 이용하면 10~30줄이 될 수도 있다.

그만큼 용이하다.

728x90

'1학년 대학 수업 > C++ 프로그래밍' 카테고리의 다른 글

12주차 예습 과제  (0) 2025.11.16
11주차 예습 과제  (0) 2025.11.08
10주차 복습 과제  (0) 2025.11.06
10주차 예습 과제  (0) 2025.11.05
9주차 복습 과제  (0) 2025.10.30