const 변수
const를 이용하여 프로그램 내에서 값을 변경하지 않도록 할 수 있다.
const float PI=3.141592;
const int NUM=123;
const는 만들면서 바로 초기화하여야 한다. 나중에 값을 바꾸려고 하면 에러가 발생한다.
NUM=100; <-- 에러 발생
함수에서 const 매개변수
int func( const int x){
명령 }
위의 함수에서 const int x를 주목하자. 매개변수가 const int 형이다.
그럼 매개변수로서 const가 와야 하는가?... 그런 의미가 아니라 func()내에서 x의 값을 변경할 수 없다는 의미이다.
아래의 문장은 오류가 없다.
int a=10;
func(a);
그러나 매개변수의 값을 바꿀려고 하면 에러가 난다.
int func2(const int x){
x=10; // 에러 발생
return 1;
}
inline함수
매크로함수와 그냥 함수의 중간적인 성격을 띤 함수이다.
일반적인 함수를 사용하면 필요할 때마다 호출하여 사용하므로 실행파일의 크기를 줄일 수 있으나 제어권의 이동이 심하므로 실행 속도가 느려진다.
매크로 함수는 컴파일시 전개되어 치환되므로 제어권 이동이 발생하지 않으므로 속도가 빠르지만 데이터형 지정을 할 수가 없고 실행파일의 용량이 커지게 된다.
인라인 함수는 컴파일시 통째로 매크로처럼 전개되어 속도면에서 큰 이득을 얻는다. 그리고 데이터형 체크를 할 수 있는 함수이다. 용량이 커지는 단점이 있긴 하지만 간단한 작업을 하는 함수의 경우 에 이용하면 매우 편리하다.
일반 멤버 함수
- 맴버 함수는 일반 C++ 함수와 크게 다를 것이 없고 선언 방식과 정의 방식 그리고 사용법에서 차이가 난다.
1. 맴버 함수의 선언
- 맴버 함수의 선언은 맴버 함수가 속한 클래스의 내부에 일반 함수의 선언과 같은 방식으로 해주면 된다.
class A {
int funcA( int );
public :
int funcB( int );
};
위에서 funcA 는 private 멤버 엑세스 콘트롤을 가지게 되어 class A의 외부에서나 하위 클래스에서 사용할 수 가 없게 되며 이는 멤버 데이터와 같다. 클래스 선언에 서 맴버 함수의 특별한 위치는 없고 작성자의 취향에 맞게 보기 좋은 위치를 선택하여 멤버 데이터와 함수를 선언하면 된다.
2. 맴버 함수의 정의
- 맴버 함수가 속한 클래스의 이름을 한정되게 사용함으 로서 그 함수가 속한 클래스를 정확히 적어 준다. 그 예를 보면
int A::funcA( int a ) { ... }
와 같다. 이 때 A::funcA 라는 한정된 맴버 함수 이름 을 사용하여야만 한다.
3. 인라인 정의
- C++ 에서는 함수 호출에 걸리는 시간을 줄여 주면서도 매크로보다 디버깅이 편한 인라인 함수를 도입하였다. 인라인으로 맴버 함수를 정의하는 방법은 두 가지가 있 다. 하나는 클래스의 선언 안에 정의하는 방법과 클래 스의 밖에 선언하는 방법이다.
class A {
int funcA( int a ) { ... }
public :
int funcB( int b ) { ... }
};
와 같다. 이때 클래스 선언의 내부임으로 A::funcA라는 식의 한정된 이름은 불필요하다. 또 한가지 방법은 inl ine 이라는 예약어를 사용하면 된다.
inline int A::funcA( int a ) { ... };
과같이 해주면 클래스의 내부에 정의한 것과 같은 효과 가 있다. 단 인라인 함수는 그 인라인 함수가 사용되는 모든 모듈의 앞부분에 정의되어 있어야만 한다. 그러므 로 인라인 함수를 클래스의 선언과 함께 헤더 화일에 넣는 것이 보통이다.
C++ 에서 인라인 함수가 가장 많이 사용되는 곳은 Muta tor 라고 불리는 private, protected 멤버 범위를 가 진 멤버 데이터의 상태를 물어보는 함수들이다. 즉,
class Point {
int x, y;
public :
int getX() const { return x; };
int getY() const { return y; };
};
맴버 함수 getX 와 getY 가하는 일은 단지 맴버 데이터 x, y 의 상태를 전달해주는 역할이다. 실제로 위와 같 은 인라인 함수는
int i = point.x; // int i = point.getX();
와 같은 직접 대입과 똑같은 크기의 코드를 만들어 낸 다. getX와 같이 단순히 어떤 맴버 데이터를 단순히 리 턴 하는 함수 등은 반드시 인라인으로 정의하여 코드의 크기도 작아지고 속도도 빠르게 하자. 단 인라인 함수 에는 for, while, do - while 등의 반복 구문은 사용할 수가 없다. 사족을 붙인다면 버그의 가능성이나 중요한 함수는 개발의 마지막 단계에서 인라인으로 선언하는 것이 좋다.
4. 맴버 함수의 오버로딩
- 인라인 함수와 함께 C++ 에 도입된 함수 정의 방식으로 같은 이름의 여러 다른 함수를 선언 및 정의하여 사용 할 수가 있는 함수들로서 맴버 함수에도 그대로 그 규 칙이 적용된다.
class A {
public :
int funcA( int );
int funcA( int, int );
int funcA( char );
int funcA( int, int, int, ... );
};
5. const 맴버 함수
- const 맴버 함수는 다음과 같이 선언된다.
class A {
public :
int funcA( int ) const { ... }
};
const 예약어가 함수의 선언 뒤에 사용된 맴버 함수를 const 맴버 함수라고 부른다. const 맴버 함수는 그 함 수 내에서는 어떤 맴버 데이터의 변형도 일어나지 않는 다는 일종의 버그의 가능성을 줄이는 효율적인 코딩을 할 수 있도록 도와주는 '선언' 이다. const 맴버 함수 내에서는 const 형이 아닌 함수를 호출할 수가 없으며 맴버 데이터도 변형할 수가 없다. 이 const 형 맴버 함 수와 const 형 함수인자를 잘 섞어서 쓰면 불필요한 버 그의 가능성을 상당 부분 줄일 수가 있으며 함수의 선 언만으로도 그 맴버 함수를 호출하여도 맴버 데이터가 변화되지 않는다는 것을 알 수 있어 코드를 읽기 편하 게 해준다.
6. 맴버 함수의 선언과 정의
- 맴버 함수의 선언은 클래스의 선언 속에서 이루어진다. 하지만 맴버 함수의 정의는 클래스 외부에서 이루어지 는 것이 보통이다. 이 때 한 클래스에 선언된 맴버함수 모두가 정의될 필요는 없다. 또 한 클래스에 선언된 맴 버 함수가 같은 모듈에 들어 있을 필요도 없다. 만일 어떤 클래스가 있고 그 클래스에 속한 맴버 함수들이 모두 사용되지 않는다면 선언된 맴버 함수들 전체가 정 의되어 있지 않아도 된다. 이런 특성을 살리면 프로그 램 개발 과정에서 많은 시간적 이득을 볼 수가 있다.
[C++ 강좌3]
C++ 언어의 기초3
상수형 데이터
C 에서도 #define에 의한 상수가 있었지만 C++ 에서는 더욱 강력히 사용되며 const 예약어를 사용하여 정의한다.
형식 : const 자료형 변수명 = 상수;
Ex)
const double pi = 3.141592;
- 상수형은 정의와 동시에 반드시 초기화가 되어야 한다.
- 상수형은 변화시킬 수도 없고, 변화해서도 안된다. - C에서와 달리 자료형의 지정이 가능해졌다.
- 이 상수형은 pointer형에서 유용하게 쓰인다.
[1] const int *p; --> 내용의 상수화 ; 주소의 변경 가능, 내용의 가능 불가
[2] int * const p; --> 주소의 상수화 ; 주소의 변경 불가, 내용의 가능 가능
[3] const int *const p; --> 내용과 주소의 상수화 ; 주소의 변경 불가, 내용의 가능 불가
new, delete 연산자에 의한 메모리의 동적할당
C 에서 malloc, free 등의 함수를 사용하던 메모리의 동적할당을 단순히 연산자 하나로서 가능해졌다.
new 연산자
형식 : 포인터변수 = new 자료형(크기);
Ex) int *i = new int; char *p = new char[5];
- new 연산자는 sizeof(할당대상)의 메모리를 heap영역에 확보하여 선두번지값을 리턴한다. 메모리 확보에 실패한 경우 _new_handler 라는 함수를 호출하여 프로그램을 종료시키나, set_new_handler함수를 사용하여 수정을 하여 섬세한 처리를 할 수가 있다. (malloc의 경우: NULL값 리턴) 이렇게 해서 동적할당된 메모리는 사용이 끝나면 반드시 해제시켜야 한다.
delete 연산자 - 메모리의 해제는 delete 연산자에 의해서 가능하다.
형식 : delete 포인터변수;
위에서 할당되었던 메모리를 해제하기 위해서는 다음과 같이 한다.
delete i; delete p;
new로 생성된 메모리를 가리키는 포인터 변수는 일반변수와 마찬가지로 사용할 수 있게 된다. class의 객체를 생성할 때는 객체를 초기화시켜 주는 함수까지 호출시킬 수 있다. 다음 예를 보면 무슨 뜻인지 알 것이다.
Ex1) int *buffer = new int[5];
for (int i = 0; i <= 4; i++) buffer[i] = i;
Ex2) struct person {
char name[15];
int age;
float height;
}
person *p = new person;
strcpy(p->name,"ACCESS");
p->age = 21;
p->height = 178.5;
};
4. linkage 지정
linkage 란?
컴파일시에 컴파일러가 오브젝트 파일에 남겨놓는 링크에 관한 정보를 말한다. 따라서 링커는 linkage 정보를 보고 어떤 함수가 결합되어야 할지 판단하게 된다. C에서는 함수끼리 이름만으로 구분이 가능했었으나 C++ 에서는 다형성에 의해서 이름만으로는 구분이 불가능하게 되었다. 따라서 C++에서 C 함수를 사용하기 위해서 컴파일러가 linkage를 C++에 알맞게 변화시키는데 이것을 네임 맹글링 (name mangling)이라고 한다.
형식 : 함수의 프로토타입 앞에 extern "C" 를 붙여주면 된다.
Ex)extern "C" int myfunc(void);
extern "C" {int myfunc(void);
void subfunc(char *c);
char *str(int n);
}
extern "C" { #include "user.h" }
어셈블러로 짜여진 모듈을 사용할 때에도 extern "C"라고 써준다.
기존에는 프로젝트 파일을 아스키문서로 작성하였으나 Borland계열의 C++ 에서 프로젝트를 하기 위해서는 IDE내의 프로젝트 파일 에디터를 사용하여 무척 쉽게 작성이 가능하다. 게다가 어셈블러 모듈까지 프로젝트에 사용할 수가 있다.
댓글 없음:
댓글 쓰기