C++에서 (C언어에서는 지원되지 않음) 함수가 호출될 때 입력 인자에 값이 넘어오지 않는다면 미리 정해진 값을 함수 내부에서 가지도록 할 수 있다. 이렇게 기본값을 가지는 함수의 인자를 기본값 인자(default parameter)라고 하며 함수의 선언부에서 예를 들면 다음과 같이 명시해 주어야 한다.


void func(int ia=0); // 함수의 선언에 ia의 기본값을 10으로 지정
….
int func(int ia) { //함수 정의. ia는 기본값 10을 가진다.
   return ia+10;
}


변수 ia는 호출될 때 값이 넘어오지 않으면 자동으로 0값을 가지도록 선언되었다. 즉, 이 함수를 호출할 때 입력인수를 주어도 되고 안 해도 된다.

func(); // 변수 ia는 0값을 자동으로 갖는다.
func(10); // 변수 ia에 10값을 넘겨준다.

 만약 디폴트 입력 인수기능이 없이 함수 중복으로만 이를 구현한다면 다음 그림의 좌측과 같이 두 개의 함수를 별도로 작성해야 할 것이다.


void func() {

   int ia = 0;

   // 함수 본체

   ....

}

void func(int ia) {

   // 함수 본체

   ....

}

void func(int ia = 0);

함수 중복으로 구현한 경우

디폴트 입력 인수 함수로 간략화


이것을 살펴보면 기본 인자 기능이 프로그램을 상당히 간결히 해주는 유용한 기능임을 알 수 있다.


#include "stdio.h"

void print(char *name = "John");// 기본값을 지정

int main(void)
{
print();
print("Jang-Hyun Park");
}

void print(char *name)
{
printf("Hi. My name is %s\n", name);
}


Hi. My name is John
Hi. My name is Jang-Hyun Park

 다른 예를 들어보면 다음과 같다.

void send(int ia, string str=“Hello”);

이 함수는 다음과 같이 두 가지로 호출이 가능하다.


send(10);
send(10, “Hi”);

 

기본값 인자가 설정된 변수만 생략 가능하다는 점에 유의해야 한다. 따라서 다음과 같은 호출은 오류를 발생시킬 것이다.

send(); //오류 발생
send(“Hi”); //오류 발생

 만약 다음과 같이 디폴트 입력 인수를 두 개 가진 함수라면

void sum(double da, double db=10.0, double dc=20,0);

다음과 같이 세 가지 방법으로 호출할 수 있다.

sum(1.0); // da는 1.0, db는 10.0, dc는 20.0 값을 갖는다.
sum(1.0, 2.0); // da는 1.0, db는 2.0, dc는 20.0 값을 갖는다.
sum(1.0, 2.0, 3.0); // da는 1.0, db는 2.0, dc는 3.0 값을 갖는다.

 디폴트 입력 인수를 가진 함수를 선언할 때 주의할 점은 이것들이 모두 끝 쪽에 몰려있어야 하며 디폴트 입력 인수를 가지는 변수 다음에 일반 변수는 못 온다는 것이다. 다음 예는 모두 잘못된 것이다.

 void sum(int ia, int ib=5, int ic, int id=10);// 에러 발생
 void sum(int ia=10, int ib, int ic);// 에러 발생

그리고 다음과 같은 함수 중복도 오류를 발생한다.


void print(string stra);
void print(string stra = “Hello”); // 허용되지 않는 함수 중복

 

그 이유는 두 함수가 입력 인수의 개수와 형이 같기 때문이다. 그리고 다음과 같은 함수 중복도 오류를 발생한다.

void func(int ia, string strA=“Hi”);
void func(int ia); // 허용되지 않는 함수 중복

두 함수는 분명히 입력 인수의 개수가 다르지만 만약 func(10) 이라고 호출했을 때 두 개 중 어느 것을 호출해도 문제가 없기 때문에 컴파일러는 오류를 발생시킨다.



Posted by 살레시오
,

 C 언어 프로그램은 같은 이름을 갖는 함수를 정의할 수 없으나 C++에서는 가능하다. 이렇게 같은 이름을 갖는 함수들을 작성하는 것을 함수 중복(overloading)이라고 하며 전역 함수와 클래스의  멤버 함수 모두에 가능하다.


 예를 들면 다음과 같다.

void print();
void print(int ia);
void print(char *str);
void print(int ia, bool bNewLine);

이 예제들의 세 개의 print()함수는 모두 같은 이름을 갖지만 입력 인자가 서로 다르므로 모두 다른 함수들이다. 이와 같이 함수의 중복이 가능하려면 각각을 구별해야 하므로 다음의 조건들을 만족해야 한다.

       ❶ 중복되는 함수들의 입력 인자의 개수가 다르거나 타입이 달라야 한다.

       ❷ 반환형만 다르고 입력 인자가 같은 중복은 허용되지 않는다.

따라서 다음의 두 함수는 함수 중복의 요건이 안 되기 때문에 오류를 발생한다.

void print(string stra);
int print(string stra);

 함수 중복을 이용하면 같은 종류의 일을 하는 서로 다른 입력 인자를 갖는 함수들을 같은 이름으로 일관성 있게 관리할 수 있으므로 무척 효율적이다. 또한 컴파일러는 함수가 호출될 때 대응되는 함수를 프로그램이 실행될 때가 아니라 컴파일할 때 결정하므로 함수 중복으로 인해서 실행 시간이 지연되는 않는다.


 다음 예를 실행해 보자.


#include "stdio.h"

void print();
void print(char *);

int main(void)
{
print(); //❶을 호출
print("Jang-Hyun Park");//❷를 호출
}

void print() //
{
printf("Hello.\n");
}

void print(char *name) //
{
print(); //❶ 을 호출
printf("My name is %s.\n", name);
}


Hello.
Hello.
My name is Jang-Hyun Park.


함수 ❷ 내부에서도 함수 ❶을 호출할 수 있음을 유의해서 보자. 사실 두 함수는 이름만 같을 뿐 내부적으로는 완전히 다른 함수로 취급되므로 이러한 상호 호출이 가능하다.



Posted by 살레시오
,

3.12 연산자 우선 순위와 결합 방향    [doc]    [smts]

3.12.1 연산자 우선 순위

한 수식에 여러 개의 연산자를 사용하는 경우에 연산자들의 우선순위를 고려하지 않을 수 없다. 연산자 우선순위를 정리하면 다음과 같다.


  1. 괄호, 배열, 구조체, 공용체멤버를 나타내는 지시자 (), [], ->, . 은 우선순위가 가장 높다.

  2. 한 개의 피연산자를 갖는 단항연산자(!, ++, -- 등)이 그 다음으로 우선순위가 높다.

  3. 그 다음은 산술 연산자 (+, - *, /, %)이다.

  4. 쉬프트연산자와 비교연산자는 비트연산자보다 연산순위가 높다.

  5. 맨 하위에 대입연산자와 콤마(,)연산자가 있다.


[표 3.12.1] 연산자 우선 순위와 결합 방향

순위

연산자

결합 방향

1

( ) [ ] -> .

2

! ~ ++ -- - + (cast) *(pointer) &(addr) sizeof

3

* / %

4

+ -

5

<< >>

6

< <= > >=

7

== !=

8

&

9

^

10

|

11

&&

12

||

13

?:

14

= += -= *= /= %= ^= |= <<= >>=

15

,


연산자 우선 순위와 결합 방향을 고려하여 프로그래밍하는 것은 프로그래머의 몫이며 프로그래밍은 가독성(간결성)과 효율(길이) 측면에서 고민하게 되는 경우가 자주 발생한다. 한 수식에 부득이하게 연산자를 여러 개를 써야 한다면 괄호 등을 적극 활용하여 우선 순위를 명확히 하는 것이 좋다.


3.12.2 연산자 결합 방향

한 수식에서 동일한 우선순위를 가진 연산자들이 연속적으로 나타나 있으면 연산자의 결합 방향을 고려하여야 한다. 대부분의 연산자들은 왼쪽에서 오른쪽으로 결합을 한다. 하지만 반대로 오른쪽에서 왼쪽으로 결합하는 연산자가 있다.


  1. 단항연산자, 형변환연산자, sizeof등은 오른쪽에서 왼쪽으로 결합한다.

  2. 조건 연산자 (?) 는 오른쪽에서 왼쪽으로 결합한다.

  3. 대입 연산자는 오른쪽에서 왼쪽으로 결합한다.


[표 3.11.1] 연산자 결합 방향 예시

수식

결합 결과

a = x +y - z

a = (x + y) - z

a = x * y / z

a = (x * y) / z

a = x && y || z

a = (x && y) || z

a = y+= z

a = (y+= z)

a = *x++

a = *(x++)


예를 들어서 sA=sY+=sZ 와 같은 표현식은 내부적으로 정해진 결합 순서에 의해서 오른쪽에서 왼쪽으로 결합하겠지만 프로그래머가 아예


sA = (sY += sZ);

와 같이 괄호를 명시하든가 더 가독성을 높이려면


sY += sZ;
sA = sY;

와 같이 두 줄로 나누어 쓰는 것이 더 나아보일 수도 있다. 이는 전적으로 작성자의 성향에 달려있다고 할 수 있다.



Posted by 살레시오
,