레이블이 멤버함수인 게시물을 표시합니다. 모든 게시물 표시
레이블이 멤버함수인 게시물을 표시합니다. 모든 게시물 표시

2015년 6월 12일 금요일

C++ 인라인(inline) 멤버 함수

 C++ 에서 함수를 호출하는데 있어서는 어느 정도 댓가가 따른다. 함수를 호출하기 직전에 기존 정보를 저장하고 인자를 넘겨주고 실행 순서를 바꾼 후 함수의 수행이 끝나면 사용한 메모리를 정리하고 반환값을 받는다. 즉 함수 호출 전후에 필수적으로 수행해야하고 메모리와 시간을 요하는 작업들이 있는 것이다. PC에서 수행되는 프로그램을 작성할 때에는 이러한 오버헤드는 무시할 수 있을 것이다. 하지만 아두이노와 같은 메모리나 성능이 매우 제약된 프로세서를 프로그래밍할 경우에는 무시 못할 성능 저하 요인이 될 수도 있다.

 C++의 인라인(inline)함수는 함수의 길이가 매우 짧을 경우에 효율을 높이기 위해서 도입된 방법으로서 함수의 선언부 앞에 inline 이라는 키워드로 구현된다. 이전의  코드로 예를 들면 다음과 같다.
inline boolean Button::isPushed() {
   return (digitalRead(_pin) == LOW)? true:false;
}

컴파일러는 인라인 함수를 호출하는 곳에 인라인 함수의 코드를 그대로 삽입하여 함수의 호출이 일어나지 않도록 한다. 이렇게 되면 함수를 호출할 때 드는 비용이 없어지기 때문에 속도가 더 올라간다. 반대 급부로 프로그램의 길이는 더 길어지게 된다.
 다른 객체지향 언어(JAVA, C# 등등)도 마찬가지지만 C++도 비교적 작은 크기의 함수를 많이 사용한다. 대표적인 것이 멤버 변수를 접근하는 getter/setter 함수인데 이러한 사용 빈도가 높고 크기가 작은 함수들을 inline으로 정의해 놓으면 더 높은 실행 효율을 얻을 수 있다.

 함수를 inline으로 설정했다고 모두 코드를 치환하는 것은 아니고 컴파일러에 따라서 동작 방식이 다르다. 자기 자신을 호출하는 재귀함수나 반복문, switch문 등이 포함된 함수는 inline으로 지정했다고 하더라도 컴파일러에 의해서 인라인 선언이 무시될 수도 있다. 또한 생성자를 포함하여 모든 멤버 함수가 인라인으로 선언될 수 있다. 이전 포스트의 Button클래스의 멤버 함수를 인라인 함수로 지정하면 다음과 같다.
class Button {
   public:
     Button(byte, boolean); // 생성자
     boolean isPushed(); // 버튼이 눌렸다면 true를 반환하는 멤버 함수
   private:
     byte _pin; // 연결된 핀
     boolean _internalPullup; //내부에 풀업이 되었는가
};
// 생성자의 구현
inline Button::Button(byte pin, boolean internalPullUp = true) {
   _pin = pin;
   _internalPullup = internalPullUp;
   if (_internalPullup)
       pinMode(_pin, INPUT_PULLUP);
   else
   pinMode(_pin, INPUT);
}
// 멤버 함수의 구현
inline boolean Button::isPushed() {
   return (digitalRead(_pin) == LOW)? true:false;
}
 멤버 함수의 크기가 작을 경우 클래스의 선언부에 바로 함수를 구현해도 무방하다. 즉, 위 예의 isPushed() 함수를 다음과 같이 클래스의 선언부에 바로 구현해도 된다.
class Button {
   public:
     Button(byte, boolean); // 생성자
     boolean isPushed();{
       return (digitalRead(_pin) == LOW)? true:false;
     }
     boolean isPushed(); // 버튼이 눌렸다면 true를 반환하는 멤버 함수
   private:
     byte _pin; // 연결된 핀
     boolean _internalPullup; //내부에 풀업이 되었는가
};
// 생성자의 구현
inline Button::Button(byte pin, boolean internalPullUp = true) {
   _pin = pin;
   _internalPullup = internalPullUp;
   if (_internalPullup)
       pinMode(_pin, INPUT_PULLUP);
   else
       pinMode(_pin, INPUT);
}
 단 한 가지 주의할 점은 컴파일러는 클래스 선언부에 바로 구현된 멤버 함수들에 대해서는 inline선언이 없어도 인라인 함수로 자동으로 처리한다. 따라서 이 예에서 isPushed()함수는 인라인 함수로 자동으로 간주된다.


2015년 5월 12일 화요일

파이썬(python)의 문자열의 멤버 함수들

 파이썬 문자열의 멤버 함수를 정리하면 다음 표와 같다.

문자열 함수
기능
format()
변수의 내용을 표시하기 위한 포맷팅을 수행한다.
lower(), casefold()
upper()
swapcase()
title()
capitalize()
대문자를 소문자로 바꾼다.
소문자를 대문자로 바꾼다.
대문자는 소문자로, 소문자는 대문자로 바꾼다.
모든 단어의 첫 문자만 대문자로 나머지는 소문자로 바꾼다.
문자열의 첫 글자만 대문자로 나머지는 소문자로 바꾼다.
islower()
isupper()
모든 문자가 소문자이면 True 반환
모든 문자가 대문자이면 True 반환
count(str)
str이 포함된 개수를 센다.
find(str)
index(str)
str의 첫 위치를 알아낸다. (없다면 -1 반환)
str의 첫 위치를 알아낸다. (없다면 예외 발생)
join(str)
str을 구성하는 각 문자 사이에 원 문자열을 끼워 넣는다.
lsrtip()
rstrip()
strip()
center(n[,str])
ljust(n[,str]))
rjust(n[,str]))
좌측 공백을 지운다.
우측 공백을 지운다.
양쪽의 공백을 지운다.
크기 n의 문자열의 중앙에 원 문자열을 정렬한다.
크기 n의 문자열의 왼쪽에 원 문자열을 정렬한다..
크기 n의 문자열의 오른쪽에 원 문자열을 정렬한다..
(두 번째 인수가 없다면 공백 문자를, 있다면 그 문자로 채운다.)
replace(str1, str2)
원 문자열 안의 str1을 str2로 바꾼다.
split()
split(sep)
공백문자를 기준으로 나누어서 리스트에 저장한다.
sep(문자열)을 기준으로 나누어서 리스트에 저장한다.
isalnum()
isalpha()
isidentifier()
모든 문자가 알파벳 혹은 숫자(alphanumeric)이면 True 반환.
모든 문자가 알파벳(alphabet)이면 True 반환.
문자열이 식별자의 조건에 맞다면 True 반환.
isdecimal()
isdigit()
isnumeric()
십진 정수이면 True 반환.
모든 문자가 0에서 9가지의 숫자이면 True 반환.
모든 문자가 0에서 9가지의 숫자이면 True 반환.
(세 함수의 차이점이 명확하지 않음.)

위의 함수들은 모두 문자열 혹은 문자열 변수에 바로 이어서 점(.)을 찍은 다음 호출할 수 있다. 예를 들면 다음과 같다.

>>> s = "HELLO"
>>> s2 = s.lower() #문자열 s를 전부 소문자로 만들어서 s2에 저장
>>> "Hi. My name is jhp.".count('jhp') #문자열에서 문자열 ‘jhp’의 개수를 센다.

 join()함수의 경우 str1.join(str2) 라고 입력하면 str2를 구성하는 각 문자의 사이에 str1을 끼워 넣어서 새로운 문자열을 생성한다.

>>>','.join('abc')
'a,b,c'
>>>'_and_'.join('jhpark')
'j_and_h_and_p_and_a_and_r_and_k'

2015년 5월 11일 월요일

C++의 클래스(class) 선언

 클래스(class)는 C++에서 지원하는 객체 지향 프로그래밍의 핵심 구조로서 이것을 정의하기 위해서는 class라는 키워드를 이용한다. C++의 클래스는 C언어의 구조체(struct)와 유사하게 개발자가 정의하는 새로운 데이터 타입이다. 구조체가 변수들만을 멤버(member)로 가질 수 있는 반면 클래스는 변수와 함수 모두를 멤버로 가질 수 있다. 멤버를 접근할 때 점(.)을 이용한다는 점은 C언어의 구조체와 동일하다. 또한 멤버들의 접근 영역을 public 이나 private 키워드를 이용하여 지정해 줄 수 있다.
 클래스는 선언부(declaration)과 구현부(implementation)로 나뉜다. 다음은 클래스를 선언하고 구현하는 기본적인 예이다.
// 클래스 선언부
class Rect {
   public:
       int width, height;
       int getArea();
};
// 클래스 구현부
int Rect::getArea() {
   return width*height;
}


멤버 함수 구현을 다음과 같이 클래스 선언부에 둘 수도 있다.
class Rect
{
   public:
       int width, height;
       int getArea()
       {
           return width*height;
       }
};
일견 후자의 경우가 더 간결해 보이고 실제로 함수 본체의 길이가 짧다면 별 문제가 없다. 하지만 멤버 함수의 구현이 길어지고 이러한 멤버 함수가 여러 개라면 클래스의 전체적인 구조를 한 눈에 파악하기가 어려워지고 가독성이 떨어지게 된다. 따라서 전자와 같이 클래스의 선언부와 멤버 함수의 구현부를 분리하는 것이 더 일반적이다.


클래스 선언부


클래스는 다음과 같이 class 키워드와 이름으로 선언한다.
class Rect { // Rect 라는 클래스 선언
   ...
}; // 반드시 세미콜론(;)으로 종료
클래스 이름은 일반적인 식별자 구성 규칙에 따라 개발자가 원하는 대로 붙이며 관습상 대문자로 시작한다. 클래스 선언은 클래스의 모양을 정의하는 것으로서 멤버 함수와 멤버 변수의 원형을 선언한다. 멤버들은 “{”와 “}” 으로 감싸고 마지막에 반드시 세미콜론(;)을 붙여야 한다.

클래스 멤버



 클래스의 멤버(member)는 변수와 함수로 구성된다. 멤버 변수는 클래스 선언부에서 초기화될 수 없다. 따라서 다음과 같은 경우 오류가 발생한다.


class Rect {
   public:
       int width = 10, height = 20;
       int getArea();
};
 
멤버 함수는 원형 형태로 선언되며 함수 선언 규칙과 동일하고 반환 타입, 입력 인수의 리스트 등이 모두 선언되어야 한다. getArea() 멤버 함수는 반환형이 int 이고 입력 인수는 없는 함수의 원형이다. 멤버 함수는 함수 선언만 클래스 선언부에 두고 함수 정의는 외부에 둘 수 있으며 멤버 함수 선언과 정의 모두 클래스 선언부에 둘 수도 있다.


클래스 구현부


 클래스 구현부에서는 클래스 선언부에 선언된 멤버 함수의 실제 코드를 작성한다. 구현부에서 작성되는 멤버함수의 소속을 지정하기 위해서 함수명 바로 앞에 className ::을 앞에 붙여야 하며 이 함수가 className 의 멤버함수라는 것을 나타낸다. 앞의 예에서


double Rect::getArea() {
   return width*height;
}


여기서 더블 콜론(::) 는 ‘범위 지정 연산자’라고 하며 함수가 어떤 클래스의 멤버인지를 지정할 때 사용되는 연산자이다.