CH06 함수 중복과 static 멤버

jiyoon·2024년 4월 24일
0

함수 중복

소멸자는 매개 변수를 가지지 않아, 중복 불가하다.


디폴트 매개 변수

제약 조건

디폴트 매개 변수는 보통 매개 변수 앞에 선언될 수 없고, 끝 쪽에 몰려 선언되어야 한다.
왜냐하면, 디폴트 매개 변수를 가지고 있는 함수의 호출문을 컴파일할 때, 컴파일러는 함수 호출문에 나열된 실인자 값들을 앞에서부터 순서대로 함수의 매개 변수에 전달하고, 나머지는 디폴트 값으로 전달하기 때문이다.


디폴트 매개 변수를 가진 함수 선언 및 호출

선언부 또는 구현부에서 디폴트 매개 변수 선언을 해주면 된다. 하지만, 중복해서 작성하면 안 된다.


포인터 변수의 디폴트 값

void f(int *p = NULL);				//어떤 객체도 가리키지 않고 있음
void g(int x[] = NULL);				//어떠한 배열(주소) 가리키지 않고 있음
void h(const char *s = "Hello");	//"Hello" 문자열을 가리킨

!!배열의 이름은 포인터이기 때문에, 다음 두 함수는 같은 함수로서, 공존할 수 없다!!
void f(int a[]);
void f(int* a);



함수 중복의 모호성

형 변환으로 인한 모호성

함수의 매개 변수 타입과 호출 문의 실인자 타입이 일치하지 않는 경우, 컴파일러는 작은 타입 -> 큰 타입으로 자동 형변환처리를 하는데, 이때 판정이 모호해지면 컴파일 오류를 발생시킨다.

참조 매개 변수로 인한 모호성

디폴트 매개 변수로 인한 모호성




static 멤버

특징

  • 생명 주기 - 객체의 생성과 상관없이 프로그램이 시작할 때 생성되고 프로그램이 종료할 때 소멸된다
  • 사용 범위 - 변수나 함수가 선언된 범위 내에서 사용. 전역 혹은 지역으로 구분
  • non-static 멤버는 클래스의 객체가 생성될 때 각 객체마다 별도로 생성되므로 인스턴스 멤버라 부르고, static 멤버는 클래스 당 하나만 생기고 모든 객체들이 공유하므로 클래스 멤버라고 부른다.
  • static 멤버 함수는 오직 static 멤버들만 접근
    • static 멤버 함수가 접근할 수 있는 것 : static 멤버 함수, static 멤버 변수, 함수 내의 지역 변수
    • static 멤버 함수는 non-static 멤버에 접근 불가
      why? 객체가 생성되지 않은 시점에서 static 멤버 함수가 호출될 수 있기 때문
    • static 멤버 함수는 객체가 생기기 전부터 호출 가능하므로 this 사용 불가하다


static 멤버 선언

static 멤버 변수는 외부에 전역 변수로 선언되어야 한다.


static 멤버 사용

객체의 멤버로 접근 가능하고, 객체가 생기기 전부터 클래스명과 범위 지정 연산자(::)로도 접근 가능하다.


static의 주요 활용

  • 전역 변수나 전역 함수를 클래스에 캡슐화
    • 전역 변수나 전역 함수를 static으로 선언하여 클래스 멤버로 선언
    • 전역 변수나 전역 함수를 가능한 사용하지 않도록
  • 객체 사이에 공유 변수를 만들고자 할 때
    • static 멤버를 선언하여 모든 객체들이 공유








6-7

static 멤버를 가진 Random 클래스 완성하기

main.cpp

#include <iostream>
#include "Random.h"
using namespace std;

int main() {
    //Random::seed();         //static 함수는 클래스 이름으로 호출
    Random r;               
    r.seed();               //객체를 생성하지 않고도 seed 함수를 호출할 수 있다. 객체 생성 없이도 사용할 수 있는 함수를 static 함수로 선언한다.

    cout << "1에서 100까지 랜덤 정수 10개 출력" << endl;
    for (int i = 0; i < 10; i++) {
        //int n = Random::nextInt();
        int n = r.nextInt(1, 100);
        cout << n << ' ';
    }
    cout << endl;

    cout << "알파벳 랜덤 10개 출력" << endl;
    for (int i = 0; i < 10; i++) {
        char c = Random::nextAlphabet();
        cout << c << ' ';
    }
    cout << endl;

    cout << "실수 랜덤 10개 출력" << endl;
    for (int i = 0; i < 10; i++) {
        double d = Random::nextDouble();
        cout << d << ' ';
    }
    cout << endl;
}

Random.h 헤더 파일

#ifndef RANDOM_H
#define RANDOM_H

#include <cstdlib>      //srand, rand 함수, RAND_MAX 상수 (32767) 포함
#include <ctime>        //time 함수 포함

class Random {
public:
    static void seed() {srand((unsigned)time(0));}
    static int nextInt(int min=0, int max=RAND_MAX); //디폴트 매개변수 사용하여 인수가 없을 때의 기본값 설정
    static char nextAlphabet();
    static double nextDouble();
};

#endif

Random.cpp

#include "Random.h"

int Random::nextInt(int min, int max) {
    int range = max - min + 1;
    return rand() % range + min;
}

char Random::nextAlphabet() {
    int n = rand() % 26;
    if (rand() % 2 == 0) 
        return 'a' + n;
    else 
        return 'A' + n;

    /*
    return (char)('a' + rand() % 52);   //소문자와 대문자를 둘 다 출력되지 않는다. 아스키코드가 연속적이지 않기 때문. 'a'는 97, 'A'는 65 임.
    */
}

double Random::nextDouble() {
    double d = ((double)rand()) / RAND_MAX; //한번 더 캐스팅을 해주어야 한다. 그렇지 않으면 정수 나누기 정수가 되어 0이 나온다.
    return d*100;
}
profile
주니어 개발자

0개의 댓글