접근 제어
클래스에서 말하는 접근 제어는 어떤 멤버를 외부에 보이게 할 것인지 지정하는 작업을 말한다. 즉 정보 은닉을 달성할 수 있는 수단이 된다.

접근 권한을 설정하기 위한 키워드로는 public, protected, private이 있고 각 키워드가 의미하는 바는 다음과 같다.
publc :
   - 외부 접근 가능(모든 클래스에서 사용 가능)
   - 다른 패키지에서도 접근 가능
protected :
   - 외부 접근 불가능(상속 관계에 있는 자식 클래스만 쓸 수 있게 만든 것)
   - 같은 패키지의 서브 클래스와 다른 패키지의 서브 클래스에서 접근 할 수 있다.
private :
   - 외부 접근 불가능(같은 클래스 안에서만 접근할 수 있다)
   - 오로지 해당 클래스 내부의 메소드만으로 접근이 가능하다.
   - 상속된 하위 클래스도 접근 불가능, 제일 강력한 접근 제어로 '정보 은닉'을 위한 장치
어떤 접근권한을 가지든지 클래스 내부의 멤버 함수에서는 모든 멤버에 접근할 수 있다.

* c++에서 구조체는 클래스가 할 수 있는 모든 일을 할 수 있다. 하지만 c언어와의 호환성을 위해서 그렇게 하지 않는 것이 일반적이다. c++에서 클래스와 구조체가 다른 점은 딱 한 가지 밖에 없다. 접근 권한과 관련된 키워드를 아무것도 적어주지 않은 경우에 클래스는 기본적으로 private 접근 권한을 적용하고, 구조체는 public 접근 권한을 적용한다.

 // 접근 권한 지정
#include <iostream>
using namespace std;

class AccessControl
{
public:
  char publicData;
  void publicFunc() 
  {

  }
protected:
  int protectedData;
  void protectedFunc()
  {

  }
private:
  float privateData;
  void privateFunc()
  {

  }
};

int main()
{
  // 객체 생성
  AccessControl ac;

  ac.publicData = 'A';    // 성공
  ac.publicFunc();      // 성공
  ac.protectedData = 100;    // 실패
  ac.protectedFunc();      // 실패
  ac.privateData = 4.5f;    // 실패
  ac.privateFunc();      // 실패

  return 0;
}


 // 멤버 함수에서 멤버에 접근하기
#include <iostream>
using namespace std;

class AccessControl
{
public:
  char publicData;
  void publicFunc()
  {

  }
protected:
  int protectedData;
  void protectedFunc()
  {

  }
private:
  float privateData;
  void privateFunc()
  {

  }
public:
  void AccessAllMembers();
};

void AccessControl::AccessAllMembers()
{
  publicData = 'A';
  publicFunc();
  protectedData = 100;
  protectedFunc();
  privateData = 4.5f;
  privateFunc();
}

int main()
{
  // 객체 생성
  AccessControl ac;

  // AccessAllMembers() 함수 호출
  ac.AccessAllMembers();

  return 0;
}

// 클래스 내부의 멤버 함수에서는 접근 권한에 상관없이 모든 멤버에 접근할 수 있다.

// 접근자를 이용해서 멤버 변수를 접근하는 프로그램
#include <iostream>
using namespace std;

// Point 클래스 정의
class Point
{
public:
  // 멤버 함수
  void Print();

  // 생성자들
  Point();
  Point(int initialX, int initialY);
  Point(const Point& pt);

  // 접근자
  void SetX(int value)
  {
    if(value < 0)
    {
      x = 0;
    }
    else if(value > 100)
    {
      x = 100;
    }
    else
    {
      x = value;
    }
  }
  void SetY(int value)
  {
    if(value < 0)
    {
      y = 0;
    }
    else if(value > 100)
    {
      y = 100;
    }
    else
    {
      y = value;
    }
  }
  int GetX()
  {
    return x;
  }
  int GetY()
  {
    return y;
  }
private:
  // 멤버 변수
  int x, y;
};

Point::Point()
{
  x = 0;
  y = 0;
}

Point::Point(int initialX, int initialY)
{
  SetX(initialX);
  SetY(initialY);
}

Point::Point(const Point& pt)
{
  x = pt.x;
  y = pt.y;
}

void Point::Print()
{
  cout << "(" << x << ", " << y << ")\n";
}

int main()
{
  // 객체 생성
  Point pt(-50200);

  // pt의 내용을 출력한다.
  pt.Print();

  return 0;
}


   타이머 카운터
오늘 실험에서는 Compare Match Count 모드로 delay를 구현해보았다.

 1초를 만드는 원리
1. Prescaler를 64로 주면 16Mhz 신호가 250000hz 신호로 바꾼다.(1초에 250000만번 카운트 할 수 있다는 의미다.)
2. OCRn 레지스터를 250으로 초기화 한다. TCNTx 레지스터와 OCRn 레지스터 값을 계속 비교해서 같아 지면 SIG_OUTPUT_COMPARE0 발생한다. 즉 1/1000(1ms)가 만들어 진다.
3.  인터럽트가 발생할 때마다 카운트를 해서 1000번을 하면 1초가 만들어진다.

Compare Match Count 모드에서는 TCNT 레지스터가 자동으로 초기화 된다.
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

#define CPU_CLOCK    16000000  // CPU clock = 16Mhz
#define TICKS_PER_SEC  1000    // Ticks per sec = 1000
#define PRESCALER    64      // 클럭의 배수

volatile unsigned int g_elapsed_time;  // 시간 변수

void initLED(void);            // LED 초기화
void setTCCR0(void);          // TCCR0 설정
void initTCNT0(void);          // TCNT0 초기화 
void setTIMSK(void);          // TIMSK 설정
void toggleLED(char *state);      // LED 반전
void sleep(unsigned int elapsed_time);  
SIGNAL(SIG_OUTPUT_COMPARE0);          // timer0의 오버플로우 함수

int main(void)
{
  char state = 0;

  initLED();

  setTCCR0();

  initTCNT0();

  setTIMSK();

  sei();  // SREG 레지스터에서 인터럽트 활성화

  while(1)
  {
    toggleLED(&state);
    sleep(1000);  // 1초 대기
  }
  return 0;
}

void initLED(void)            // LED 초기화
{
  DDRF = 0xff;
  PORTF = 0xff;
}

void setTCCR0(void)            // TCCR0 설정
{
  TCCR0 = 0x0C;  // Compare Match Count 모드, Prescaler 64로 설정
}

void initTCNT0(void)
{
  OCR0 = (CPU_CLOCK / TICKS_PER_SEC / PRESCALER);  // OCR0 초기화
}

void setTIMSK(void)            // TIMSK 설정
{
  TIMSK = 0x02;  //Compare Match 인터럽트 활성화
}

void toggleLED(char *state)        // LED 반전
{
  if(*state == 1)
  {
    PORTF = 0x00;
    *state = 0;
  }
  else
  {
    PORTF = 0xff;
    *state = 1;
  }
}

void sleep(unsigned int elapsed_time)
{
  g_elapsed_time = 0;

  while(g_elapsed_time < elapsed_time);
}

SIGNAL(SIG_OUTPUT_COMPARE0)          // timer0의 오버플로우 함수
{
  g_elapsed_time++;
}


+ Recent posts