GDI(Graphic Device Interface)

  윈도우가 하드웨어를 제어할 수 있도록 응용 프로그램에 제공하는 모든 기능

  응용 프로그램과 디바이스 드라이버의 중간 역활

  응용 프로그램에 대한 장치 독립적인 그래픽 동작 수행

GDI 기본 구성 요소

  선과 곡선 (직선, 사각형, 타원, 호, 등)

  채워진 영역 (브러시 개체를 이용 - 색상, 패턴, 비트맵 이미지)

  비트맵 (디스플레이 장치의 픽셀과 일치하는 직사각형 배열, 래스터 그래픽의 기본적인 도구)

  택스트


DC(Device Context)

1)핸들 역활

애플리케이션과 출력 장치를 연결하는 역활

애플리케이션이 출력에 대한 허가를 얻고, 그려지는 영역을 결정하는 역활

2)GDI에 의해 내부적으로 유지되는 데이터 구조

여러 가지 그래픽 속성에 대한 값(텍스트 속성/색상, 매핑 모드, 글꼴)을 가짐


DC를 사용할 경우 독립적인 하드웨어 출력을 할 수 있어 출력장치에 상관없이 동일한 방법으로 출력을 설정할 수 있음

DC를 사용후 해제(리소스 반환)해야함

DC를 얻는 방법

 

  1. OnDraw(), OnPaint()함수 호출시
    윈도우나 클라이언트 영역이 다시 그려져야 할 경우 수행. MFC 내부 코드에 DC를 해제함
  2. GetDC() 함수 호출시
    반환된 포인터 값을 사용. ReleaseDC()함수를 호출하여 해제해야함. 
    일시적으로 DC를 얻는 방법이기 때문에 윈도우 크기가 변하면 내용이 사라짐
  3. CClinetDC 클래스 사용시
    CDC 클래스의 파생 클래스. DC 생성/해제를 자동적으로 수행
    윈도우에 대한 핸들 값 필요. 일시적으로 윈도우의 클라이언트 영역에서 그래픽 개체를 사용할 경우 사용
  4. CWindowDC 클래스 사용시
    윈도우 영역에 그래픽 요소를 출력할 때 사용
    GetWindowDC()함수를 이용하여 CWindowDC 클래스의 인스턴스를 포인터형태로 넘겨 받아 사용
    ReleaseDC()함수로 해제해야함

 

GDI 객체 사용 방법

 

  1. GDI 객체 생성 - 클래스의 Create계열 함수 사용
  2. DC에 객체 등록 - SelectObject()함수로 등록. 기존 설정된 객체는 포인터로 저장됨
  3. DC를 사용하여 그래픽 출력
  4. 이전 객체로 환원
  5. 객체를 삭제 - DeleteObject()함수 이용


'프로그래밍 > C++' 카테고리의 다른 글

(MFC) 대화상자  (0) 2016.07.09
(MFC) 메시지 처리  (0) 2016.07.09
(C++) 클래스와 객체  (0) 2016.07.09
(C++) Simple 한/영사전 예제  (0) 2016.07.09
(C++) 상속을 이용한 간단한 계산 클래스 구현  (0) 2016.07.09

대화상자 : 사용자와 윈도우간의 인터페이스


CDialogEx 클래스

  • 대화상자는 CDialogEx 클래스로 정의
  • 모든 윈도우 메시지 처리 가능

▲대화상자 계층도


다이얼로그 기반의 프로그램 = 애플리케이션 클래스 + 다이얼로그 클래스로 구성

 

 

클래스

기저 클래스

설 명

애플리케이션 클래스

CWinApp

프로젝트 전체를 관리하는 클래스

다이얼로그 클래스

CDialogEx

대화상자의 기능을 구현하는 실제적인 클래스

도움말 대화상자 클래스

CDialogEx

도움말 정보 클래스

 


  

▲ 대화 상자 프로그램의 동작 순서


MFC 기본 컨트롤

 

  • Static Text : 화면에 문자열 배치시 사용하는 컨트롤
  • Edit Control : 문자열을 입력하고 편집할 수 있는 컨트롤
  • Group Box : 서로 연관된 컨트롤을 시각적으로 그룹 지어 다른 컨트롤과 구분하는 용도로 사용. 그룹 박스로 묶어도 기능은 유지
  • Button Control : 마우스로 클릭하여 어떤 동작을 수행하는 용도로 사용하는 컨트롤
  • Check Box : 버튼 컨트롤의 일종으로 독립적인 옵션을 선택할 때 사용하는 컨트롤.여러 옵션 중 임의 개수를 선택시 사용.(on/off)
  • Radio Button : 상호 배타적인 옵션을 선택할 때 사용하는 컨트롤. 여러 옵션 중 하나만 선택시 사용
  • List Box : 여러 개의 선택 항목을 나열하고 선택할 수 있도록 해주는 컨트롤. 하나 이상을 선택할 수 있음
  • Combo Box : Edit Control + List Box. 

 

모달(Modal) 대화상자

 

  • 모달 대화상자 출력시 부모 윈도우에서 작업할 수 없음 (포커싱이 모달 대화상자로 됨)
  • DoModal()함수를 이용하여 출력

모덜리스(Modeless) 대화상자

 

  • 모달 대화상자와는 달리 모덜리스 대화상자는 닫지 않고도 애플리케이션 내의 다른 윈도우에서 작업할 수 있고 다시 대화상자로 돌아와 작업할 수 있는 대화상자
  • 생성 방법 : 대화상자에 대한 변수 선언 -> create()함수로 대화상자 생성 -> 생성한 대화상자 화면에 표시
    (CExDialogDlg m_Dlg; -> m_Dlg.Create(대화상자 ID,부모 윈도우의 포인터); -> m_Dlg.ShowWindow(SW_SHOW);) 

 

 

공용 대화상자

File 대화상자

  • CFileDialog 클래스로 정의
  • 파일을 선택할 수 있는 대화상자가 뜸

Font 대화상자

  • CFontDialog 클래스로 정의
  • 텍스트 기반 애플리케이션에서 사용
  • 글꼴, 크기, 문자 속성 등을 지정할 수 있는 대화상자

 

Color 대화상자


'프로그래밍 > C++' 카테고리의 다른 글

(MFC) 그래픽 객체의 사용  (0) 2016.07.09
(MFC) 메시지 처리  (0) 2016.07.09
(C++) 클래스와 객체  (0) 2016.07.09
(C++) Simple 한/영사전 예제  (0) 2016.07.09
(C++) 상속을 이용한 간단한 계산 클래스 구현  (0) 2016.07.09

메시지 : 발생된 이벤트의 종류와 정보를 전달하는 일종의 상수 값

윈도우 프로그래밍에서 가장 중요한 것은 메시지를 처리하는 것

 

  • 윈도우 메시지
    • WM_로 시작하는 메시지
    • 매개 변수가 있어 메시지를 어떻게 처리할 것인지를 결정
    • 윈도우 관리 메시지 : 윈도우의 상태가 바뀔 때 발생
    • 초기화 메시지 : 응용 프로그램이 메뉴나 대화상자를 구성할 때 발생
    • 입력 메시지 : 마우스, 키보드로 입력할 때 발생
  • 컨트롤 통지 메시지
    • Button, Combo Box와 같은 제어 객체나 자식 윈도우에서 부모 윈도우로 보내는 메시지
  • 명령 메시지
    • 메뉴, 툴바, 엑셀레이터 키와 같은 사용자 인터페이스 객체로부터 발생되는 WM_COMMAND 메시지
    • 명령메시지는 윈도우뿐만 아니라 도큐먼트, 도큐먼트 템플릿, 뷰, 다른 애플리케이션 객체에 의해서도 발생될 수 있음

 

 


Win32 SDK 프로그램 : 들어온 메시지를 switch문을 사용하여 처리

MFC : 메시지 처리를 위해 메시지 맵을 사용

메시지 맵(Message Map)

 

  • 메시지 번호와 메시지가 발생하였을 때 호출되는 함수의 포인터 등의 정보를 갖고 있는 테이블
  • 프로그램에 전달된 메시지와 메시지 핸들러 함수를 연결하는데 사용
  • 파생 클래스의 메시지 핸들러 함수가 우선

메시지 처리 단계 - 클래스 마법사가 2번까지 자동으로 코딩해줌

 

  1. 선언 - 윈도우 클래스의 멤버함수로 메시지 핸들러 함수를 선언
  2. 묶기 - 메시지 맵에 메시지와 메시지 핸들러 함수를 묶는 메시지의 매크로를 추가
  3. 구현 - 메시지 핸들러 함수의 기능 구현

메시지 핸들러 함수

 

  • 윈도우로부터 애플리케이션에 메시지가 전달될 때 해당 메시지를 처리하는 멤버 함수
  • 함수 이름
    • 윈도우 메시지의 WM_을 떼고 대신 On을 붙여 시작
    • 함수 선언시 afx_msg는 메시지 핸들러 함수를 나타내는 말

 

 

 

 

메시지 유형

발생 상황

메시지 핸들러 함수

WM_CREATE

윈도우가 생성될 때

OnCreate()

WM_ACTIVE

윈도우가 활성화 될 때

OnActive()

WM_PAINT

윈도우가 다시 그려질 때

OnPaint()

WM_SIZE

윈도우 크기가 변경될 때

OnSize()

WM_MOVE

윈도우가 움직일 때

OnMove()

WM_TIMER

설정된 타이머 시간이 됐을 때

OnTimer()

WM_DESTROY

윈도우가 종료될 때

OnDestroy()

 

       ▲윈도우 관리 메시지와 메시지 핸들러 함수


'프로그래밍 > C++' 카테고리의 다른 글

(MFC) 그래픽 객체의 사용  (0) 2016.07.09
(MFC) 대화상자  (0) 2016.07.09
(C++) 클래스와 객체  (0) 2016.07.09
(C++) Simple 한/영사전 예제  (0) 2016.07.09
(C++) 상속을 이용한 간단한 계산 클래스 구현  (0) 2016.07.09

객체지향 프로그래밍의 특징

다형성과 연산자 오버로딩

 

  • 다형성 : 동일한 함수나 연산자를 자료에 따라 다르게 동장하도록 적용할 수 있음
  • 연산자 오버로딩 : 사용 중인 연산자를 다른 용도로 다시 정의해 사용할 수 있게 하는 것.

상속성

 

  • 특정 객체의 성격을 다른 객체가 상속받아 사용할 수 있도록 하는 것
  • 자식 클래스가 부모 클래스의 메소드와 멤버변수를 상속받아 사용함

새로운 자료형(클래스) = 데이터의 저장(멤버변수) + 데이터를 처리할 메소드(멤버함수)

기존 C에 있던 구조체(각종 데이터 형의 모음)를 확장한 개념이다.

접근 지정자

현재 클래스

클래스 밖

private

o

x

public

o

x

 

private

 

  • 접근 지정자가 생략되면 디폴트로 private가 적용된다. 하지만 private:를 명시적으로 기술할 수있다.
  • private 멤버의 사용범위는 소속된 클래스내의 멤버함수로 국한된다.(데이터 은닉)
  • 일반적으로 멤버 변수를 private으로 설정한다.

public

 

  • public 멤버로 지정하기 위해 public:을 명시적으로 기술하여야한다.
  • 클래스 내의 멤버함수에서는 물론 객체가 선언되어 있는 영역이라면 어디서든지 객체명 다음에 멤버참조 연산자(.)로 연결하여 멤버함수를 사용할 수 있다.
  • private 멤버변수를 처리하기 위한 목적으로 작성하는 멤버함수는 일반적으로 public 멤버로 설정한다.

 

 

클래스의 선언

//클래스 선언

class 클래스명{

접근 지정자:

    자료형 멤버변수;

접근 지정자:

    자료형 멤버함수();

};

//멤버함수 정의

자료형 클래스명::멤버함수(){


}


클래스의 멤버함수 구현

 

  • 멤버함수를 정의할 때 그 함수가 어느 클래스에 소속되는지 나타내기 위해 함수의 이름 앞에 클래스 명을 명시한다. 이 때 클래스명 다음에 스코프연산자(::)을 사용한다.
  • 클래스의 멤버함수(=메소드)를 정의하는 목적 : 클래스 내에 정의된 private 멤버를 접근

객체 선언과 멤버 참조

클래스명 객체명1,...,객체명n;


클래스 멤버의 접근 방법

객체명.멤버변수;

객체명.멤버함수();


인라인 함수

함수가 호출되는 부분에 함수 내의 코드를 직접 넣어 '매크로' 처럼 처리해주는 예약어

inline 반환타입 클래스명::멤버함수명()


const 상수

변수를 상수로 만들어주는 예약어

값을 바꿀 수 없다.

const 자료형 변수명 = 초기값;

멤버 함수 매개변수 뒤에 const를 붙일 경우 함수 내에서 값을 변경하지 못하게 한다.


함수의 오버로딩

동일한 이름으로 함수를 여러번 정의하여 사용할 수 있다.

같은 의미로 사용하는 함수를 모두 다른 이름으로 정의시 프로그램을 작성할 때 함수명을 개별적으로 외워야함

 

  • 함수의 이름이 동일
  • 매개변수의 개수가 다름
  • 매개변수의 반환 자료형이 다름

 

ex) void print(int); void print(long); void print(int, long);



함수의 디폴트 매개변수

ex) void print(int x=10,int y=20, int z=30)


print(4,5,6);  => x=4 y=5 z=6

print(4,5);    => x=4 y=5 z=30

print(4);      => x=4 y=20 z=30

print();       => x=10 y=20 z=30


생성자

 

  • 기본 자료형으로 변수를 선언할 때 선언과 동시에 값을 주는 것을 초기화라고 함
  • 클래드가 객체를 생성할 때 기본 자료형처럼 초기값을 줄 수 있게 하는 역활
  • 생성자 이름은 클래스 이름과 동일
  • 자료형(반환값의 유형)을 지정하지 않음
  • 생성자의 호출은 명시적이지 않음 (객체를 선언 또는 생성 할때 컴파일러에 의해 자동으로 호출)
  • 객체의 초기화란 멤버변수의 초기화를 의미
  • 생성자도 오버로딩이 가능함

소멸자

 

  • 객체가 소멸될 때 자동으로 호출
  • 리소스 해제 작업을 위한 함수로 쓰임
  • 클래스 이름 앞에 ~(틸드)기호를 붙임
  • 자료형을 지정하지 않음
  • 호출이 명시적이지 않음
  • 객체 소멸시 자동으로 호출됨
  • 전달 매개변수를 지정할 수 없음(오버로딩 불가능)


'프로그래밍 > C++' 카테고리의 다른 글

(MFC) 대화상자  (0) 2016.07.09
(MFC) 메시지 처리  (0) 2016.07.09
(C++) Simple 한/영사전 예제  (0) 2016.07.09
(C++) 상속을 이용한 간단한 계산 클래스 구현  (0) 2016.07.09
(C++) 상속성  (0) 2016.07.09

검색한 단어와 동일한 단어가 존재할 경우 : 한글->영어, 영어->한글 로 변환

없을 경우 : 재검색 하면서 검색단어와 사전의 단어 앞글자가 일치하는 경우를 출력


실행 환경 : 실행파일과 같은 폴더에 dictionaly.txt 파일이 존재할 것

 

1
2
3
4
5
6
7
8
9
학교
school
학생
student
사랑
love
반복
loop
-1
cs

 

▲dictionaly.txt format


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
void main() {
    
    ifstream in("dictionaly.txt");
    string strDictionaly[100][2], seachWord;
    char strTemp[100];
    int t = 0, cnt = 0;
    //사전 불러오기
    while (1)
    {
        in.getline(strTemp, 100);
        if (!strcmp(strTemp, "-1")) break;
        if (!t)
        {
            strDictionaly[cnt][t] = strTemp;
            t = 1;
        }
        else {
            strDictionaly[cnt][t] = strTemp;
            cnt++;
            t = 0;
        }
    }
    int i, j;
    bool isSerach;
    while (1) {
        cout << "검색할 단어를 입력하세요 (종료 : -1)" << endl;
        cin >> strTemp;
        seachWord = strTemp;
        //종료 메시지일 경우 반복문 탈출
        if (seachWord =="-1")
        {
            cout << "사전 프로그램을 종료합니다." << endl;
            break;
        }
        //사전 검색
        isSerach = false;
        for (i = 0; i <= cnt; i++)
        {
            for (j = 0; j < 2; j++) {
                //동일한 단어 찾을 경우 탈출
                if (strDictionaly[i][j] == seachWord)
                {
                    isSerach = true;
                    goto a10;
                }
            }
        }
    a10:;
        //동일 단어 찾을 경우
        if (isSerach)
        {
            //영어->한글 한글->영어 로 배열 인덱스 변환
            j = (j == 0 ? 1 : 0);
            cout << strDictionaly[i][j] << endl;
        }
        else {
            //동일 단어 없을시 앞글자가 동일한 단어 출력
            isSerach = false;
            for (i = 0; i <= cnt; i++)
            {
                for (j = 0; j < 2; j++) {
                    if (strDictionaly[i][j].find(seachWord) == 0)
                    {
                        isSerach = true;
                        cout << strDictionaly[i][j] << " ";
                    }
                }
            }
            //그런 단어도 없을 경우 검색 실패
            if (!isSerach)
            {
                cout << "검색 결과가 없습니다.";
            }
            cout << endl;
        }
    }
}
cs

 


출력 결과

 


'프로그래밍 > C++' 카테고리의 다른 글

(MFC) 메시지 처리  (0) 2016.07.09
(C++) 클래스와 객체  (0) 2016.07.09
(C++) 상속을 이용한 간단한 계산 클래스 구현  (0) 2016.07.09
(C++) 상속성  (0) 2016.07.09
(C++) 연산자 오버로딩  (0) 2016.07.09



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include<iostream>
using namespace std;
 
class Calc {
protected:
    int a, b;
    char c;
public:
    Calc(int new_a, int new_b,char new_c);
    void Prn();
};
void Calc::Prn() {
    cout << "a : "<< a << "\tb : " << b<<"\tc : " << c << endl;
}
Calc::Calc(int new_a, int new_b, char new_c) : a(new_a), b(new_b), c(new_c)
{
}
 
class Add : public Calc {
protected:
    int c;
public:
    Add(int new_a, int new_b);
    void Sum();
    void Prn();
};
void Add::Sum() {
    c = a + b;
}
Add::Add(int new_a, int new_b) : Calc(new_a, new_b,'+') ,c(0)
{
}
void Add::Prn() {
    cout << a << " + " << b << " = " << c << endl;
}
 
class Sub : public Calc {
protected:
    int c;
public:
    Sub(int new_a, int new_b);
    void Sum();
    void Prn();
};
void Sub::Sum() {
    c = a - b;
}
Sub::Sub(int new_a, int new_b) : Calc(new_a, new_b, '-'), c(0)
{
}
void Sub::Prn() {
    cout << a << " - " << b << " = " << c << endl;
}
 
class Mul : public Calc {
protected:
    int c;
public:
    Mul(int new_a, int new_b);
    void Sum();
    void Prn();
};
void Mul::Sum() {
    c = a * b;
}
Mul::Mul(int new_a, int new_b) : Calc(new_a, new_b, '*'), c(0)
{
}
void Mul::Prn() {
    cout << a << " * " << b << " = " << c << endl;
}
 
class Div : public Calc {
protected:
    double c;
public:
    Div(int new_a, int new_b);
    void Sum();
    void Prn();
};
void Div::Sum() {
    c = (double)a / b;
}
Div::Div(int new_a, int new_b) : Calc(new_a, new_b, '/'), c(0)
{
}
void Div::Prn() {
    cout << a << " / " << b << " = " << c << endl;
}
 
void main() {
    Calc x(35'-');
    x.Prn();
 
    Add y(35);
    y.Sum();
    y.Prn();
 
    Sub z(35);
    z.Sum();
    z.Prn();
 
    Mul a(35);
    a.Sum();
    a.Prn();
 
    Div b(35);
    b.Sum();
    b.Prn();
}
cs

 


 


'프로그래밍 > C++' 카테고리의 다른 글

(C++) 클래스와 객체  (0) 2016.07.09
(C++) Simple 한/영사전 예제  (0) 2016.07.09
(C++) 상속성  (0) 2016.07.09
(C++) 연산자 오버로딩  (0) 2016.07.09
(C++) 클래스 객체  (0) 2016.07.09

상속

부모 클래스를 물려받아 자식클래스가 그대로 사용할 수 있는 것

이미 정의된 클래스를 상속받아 사용 할 수 있는 장점

부모가 되는 클래스 : 기반 클래스, 기초 클래스, 베이스 클래스

자식 클래스 : 파생 클래스


 접근 지정자

자신의 클래스

파생 클래스

클래스 외부

 private

O

X

X

protected

O

O

X

 public

O

O

O


파생 클래스 사용 방법


class 파생 클래스 : 접근 지정자 기반 클래스{

    멤버변수:

    멤버함수:

};


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<iostream>
 
using namespace std;
 
class Calc {
protected:
    int a, b, c;
public:
    void Init(int new_a, int new_b);
    void Prn();
};
void Calc::Init(int new_a, int new_b) {
    a = new_a;
    b = new_b;
    c = 0;
}
void Calc::Prn() {
    cout << "a : "<< a << "\tb : " << b << "\tc : " << c << endl;
}
 
 
class Add : public Calc {
public:
    void Sum();
};
void Add::Sum() {
    c = a + b;
}
 
 
class Mul : public Calc {
public:
    void Gob();
};
void Mul::Gob() {
    c = a*b;
}
 
 
void main() {
    Add x;
    Mul y;
    x.Init(35);
    y.Init(27);
    x.Sum();
    x.Prn();
    y.Gob();
    y.Prn();
}
cs

 

▲부모 클래스와 파생 클래스 생성 예제




상속관계에서의 생성자와 소멸자

생성자와 소멸자는 맴버함수지만 상속이 불가능

파생 객체가 생성시 부모 클래스의 생성자 까지 연속적으로 자동 호출됨

즉, 위 예제의 Add 클래스를 생성할때 Calc 생성자도 호출되며 메모리 공간엔 Calc+Add 만큼 공간을 차지하게 됨


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include<iostream>
 
using namespace std;
 
class Base {
public:
    Base();
    ~Base();
};
 
Base::Base() {
    cout << "부모 클래스의 생성자 호출" << endl;
}
Base::~Base() {
    cout << "부모 클래스의 소멸자 호출" << endl;
}
 
class Dervied : public Base{
public:
    Dervied();
    ~Dervied();
};
Dervied::Dervied() {
    cout << "파생 클래스의 생성자 호출" << endl;
}
Dervied::~Dervied() {
    cout << "파생 클래스의 생성자 호출" << endl;
}
void main() {
    Dervied obj;
}
cs

▲상속관계에서의 생성자와 소멸자


 


부모 클래스의 생성자가 인자값이 필요한 경우 다음과 같이 전달할 수 있다.


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include<iostream>
 
using namespace std;
 
class Calc {
protected:
    int a, b, c;
public:
    Calc();
    Calc(int new_a, int new_b);
    void Prn();
};
void Calc::Prn() {
    cout << "a : "<< a << "\tb : " << b << "\tc : " << c << endl;
}
Calc::Calc() {
    a = 0; b = 0; c = 0;
}
Calc::Calc(int new_a, int new_b) : a(new_a), b(new_b), c(0)
{
}
 
class Add : public Calc {
public:
    void Sum();
    Add(int new_a, int new_b);
    Add();
};
void Add::Sum() {
    c = a + b;
}
Add::Add(int new_a, int new_b) : Calc(new_a, new_b) 
{
}
Add::Add() : Calc() {
 
}
 
void main() {
    Calc x(35);
    x.Prn();
    Add y(35);
    y.Prn();
    Add z;
    z.Prn();
}
cs

 

▲상속 관계에서 생성자 문제 해결하기




오버라이딩

이미 정의된 함수를 파생클래스에서 다시 정의하는 것(재정의)

부모 클래스에서 정의된 함수의 원형과 동일한 형태여야 함


오버로딩 : 같은 함수이름을 매개변수와 반환타입을 다르게하여 여러개 정의하는 것

오버라이딩 : 상속받은 함수를 재정의 하는 것


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include<iostream>
 
using namespace std;
 
class Calc {
protected:
    int a, b;
public:
    Calc();
    Calc(int new_a, int new_b);
    void Prn();
};
void Calc::Prn() {
    cout << "a : "<< a << "\tb : " << b << endl;
}
Calc::Calc() : a(0),b(0)
{
}
Calc::Calc(int new_a, int new_b) : a(new_a), b(new_b)
{
}
 
class Add : public Calc {
protected:
    int c;
public:
    Add(int new_a, int new_b);
    Add();
    void Sum();
    void Prn();
};
void Add::Sum() {
    c = a + b;
}
Add::Add(int new_a, int new_b) : Calc(new_a, new_b) ,c(0)
{
}
Add::Add() : Calc(), c(0) {
 
}
void Add::Prn() {
    cout << a << " + " << b << " = " << c << endl;
}
 
class Mul : public Calc {
protected:
    int c;
public:
    Mul(int new_a, int new_b);
    Mul();
    void Gob();
    void Prn();
};
void Mul::Gob() {
    c = a * b;
}
Mul::Mul(int new_a, int new_b) : Calc(new_a, new_b), c(0)
{
}
Mul::Mul() : Calc(), c(0) {
 
}
void Mul::Prn() {
    cout << a << " * " << b << " = " << c << endl;
}
 
void main() {
    Calc x(35);
    x.Prn();
    Add y(35);
    y.Sum();
    y.Prn();
    Mul z(35);
    z.Gob();
    z.Prn();
}
cs

 

▲오버라이딩 예제


 


객체를 다루기 위한 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include<iostream>
using namespace std;
 
class Complex {
private:
    int real;
    int image;
public:
    Complex(int r = 0int i = 0);
    void showComplex();
    Complex sum(Complex rightHand);
};
 
void Complex::showComplex() {
    cout << "( " << real << " + " << image << "i )" << endl;
}
 
Complex::Complex(int r, int i) {
    real = r;
    image = i;
}
 
Complex Complex::sum(Complex rightHand) {
    Complex res;
    res.real = this->real + rightHand.real;
    res.image = this->image + rightHand.image;
    return res;
}
 
 
void main() {
    Complex x(1020), y(2040);
    Complex z;
    z = x.sum(y);
    x.showComplex();
    y.showComplex();
    z.showComplex();
}
cs

 

▲두 객체의 합을 클래스로 반환하는 메소드를 사용한 예



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include<iostream>
using namespace std;
 
class Complex {
private:
    int real;
    int image;
public:
    Complex(int r = 0int i = 0);
    void showComplex();
    friend Complex sum(Complex leftHand, Complex rightHand);
};
 
void Complex::showComplex() {
    cout << "( " << real << " + " << image << "i )" << endl;
}
 
Complex::Complex(int r, int i) {
    real = r;
    image = i;
}
 
Complex sum(Complex leftHand, Complex rightHand) {
    Complex res;
    res.real = leftHand.real + rightHand.real;
    res.image = leftHand.image + rightHand.image;
    return res;
}
 
 
void main() {
    Complex x(1020), y(2040);
    Complex z;
    z = sum(x, y);
    x.showComplex();
    y.showComplex();
    z.showComplex();
}
cs

 

▲프렌드 함수로 두 객체의 합을 구하는 메소드 예

 

friend : 클래스에 private된 멤버변수를 외부함수에서 사용할 수 있도록 하는 키워드

데이터 보안에 문제가 있으므로 남발하면 안됨



클래스에서 선행처리, 후행처리 하는 방법

real의 값을 1 더하는 행동

++this->real -> 선행처리

this->real++ -> 후행처리

복사된 값을 넘겨주느냐 더한값을 넘겨주느냐에 따라 선행과 후행이 결정됨


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<iostream>
using namespace std;
 
class Complex {
private:
    int real;
    int image;
public:
    Complex(int r = 0int i = 0);
    void showComplex();
    Complex addOnePreFix();
    Complex addOnePostFix();
};
 
void Complex::showComplex() {
    cout << "( " << real << " + " << image << "i )" << endl;
}
 
Complex::Complex(int r, int i) {
    real = r;
    image = i;
}
//선행처리
Complex Complex::addOnePreFix() {
    ++this->real;
    ++this->image;
    return *this;
}
//후행처리
Complex Complex::addOnePostFix() {
    Complex temp;
    temp = *this;
    ++this->real;
    ++this->image;
    return temp;
}
void main() {
    Complex x(1020), y(2040);
    Complex z;
    cout << "---- 선행처리 ----"<<endl;
    z = x.addOnePreFix();
    x.showComplex();
    z.showComplex();
 
    cout << "---- 후행처리 ----" << endl;
    z = y.addOnePreFix();
    y.showComplex();
    z.showComplex();
}
cs

 


 

출력결과

 


프렌드 함수를 이용한 구현


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<iostream>
using namespace std;
 
class Complex {
private:
    int real;
    int image;
public:
    Complex(int r = 0int i = 0);
    void showComplex();
    friend Complex &addOnePreFix(Complex &Operand);
    friend Complex addOnePostFix(Complex &Operand);
};
 
void Complex::showComplex() {
    cout << "( " << real << " + " << image << "i )" << endl;
}
 
Complex::Complex(int r, int i) {
    real = r;
    image = i;
}
//선행처리
Complex &addOnePreFix(Complex &Operand) {
    ++Operand.real;
    ++Operand.image;
    return Operand;
}
//후행처리
Complex addOnePostFix(Complex &Operand) {
    Complex temp;
    temp = Operand;
    ++Operand.real;
    ++Operand.image;
    return temp;
}
void main() {
    Complex x(1020), y(2040);
    Complex z;
    cout << "---- 선행처리 ----" << endl;
    z = addOnePreFix(x);
    x.showComplex();
    z.showComplex();
 
    cout << "---- 후행처리 ----" << endl;
    z = addOnePostFix(y);
    y.showComplex();
    z.showComplex();
}
cs

 


연산자 오버로딩


C++에서 기본 자료형으로 사용하고 있는 연산자를 재정의 하는 것

연산자도 함수로 취급하기 때문에 함수를 정의하는 방법과 동일 한 방법으로 연산자를 오버로딩할 수 있음

오버로딩 된 연산자를 연산자함수(Operator Function)이라고 함

연산에 참여하는 피연산자는 연산자를 정의할 때 매개변수로 구현하여 사용

매개변수 자료형에 의해 그 연산자를 사용할 수 있는 자료형이 결정됨


반환값 operator연산자(매개변수1,매개변수2,...)

{

함수의 본체

}


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include<iostream>
using namespace std;
 
class Complex {
private:
    int real;
    int image;
public:
    Complex(int r = 0int i = 0);
    void showComplex();
    Complex operator+(Complex rightHand);
    Complex operator-(const Complex &rightHand) const;
    Complex operator-() const;
};
 
void Complex::showComplex() {
    if (image > 0)
        cout << "(" << real << "+" << image << " i)" << endl;
    else if (image < 0)
        cout << "(" << real << image << " i)" << endl;
    else
        cout << real << endl;
}
 
Complex::Complex(int r, int i) {
    real = r;
    image = i;
}
 
//연산자 +를 오버로딩
Complex Complex::operator+(Complex rightHand) {
    Complex res;
    res.real = this->real + rightHand.real;
    res.image = this->image + rightHand.image;
    return res;
}
//연산자 -를 오버로딩
Complex Complex::operator-(const Complex &rightHand) const{
    Complex res;
    res.real = this->real - rightHand.real;
    res.image = this->image - rightHand.image;
    return res;
}
//부호 변경
Complex Complex::operator-() const 
{
    Complex res;
    res.real = -real;
    res.image = -image;
    return res;
}
void main() {
    Complex x(1020), y(2040);
    Complex z;
    cout << "---- 두 Complex 객체에 대한 덧셈 ----" << endl;
    z = x + y;
    x.showComplex();
    y.showComplex();
    z.showComplex();
 
    cout << "---- 두 Complex 객체에 대한 뺄셈 ----" << endl;
    z = x - y;
    x.showComplex();
    y.showComplex();
    z.showComplex();
 
    cout << "---- Complex 객체의 부호 변경 ----" << endl;
    z = -x;
    x.showComplex();
    z.showComplex();
}
cs

 


출력결과


 


cout에서 출력할 때 사용하는 << 연산자도 연산자오버로딩이 가능함.


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
using namespace std;
 
class Complex {
private:
    int real;
    int image;
public:
    Complex(int r = 0int i = 0);
    friend ostream &operator<<(ostream &os, const Complex &comObj);
};
 
Complex::Complex(int r, int i) {
    real = r;
    image = i;
}
ostream &operator<<(ostream &os, const Complex &comObj) {
    os << "( " << comObj.real << " + " << comObj.image << "i )" << endl;
    return os;
}
void main() {
    Complex x(1020);
    cout << x;
}
cs

 


출력결과

 



객체 포인터 변수 선언
클래스명 *객체 포인터 변수;
화살표(->) 연산자 사용가능
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include<iostream>
using namespace std;
 
class Complex
{
private:
    int real;
    int image;
public:
    Complex(int r = 0int i = 0);
    void ShowComplex() const;
};
 
Complex::Complex(int r, int i) : real(r), image(i)
{
}
 
void Complex::ShowComplex() const
{
    cout << "( " << real << " + " << image << "i )" << endl;
}
 
void main() {
    Complex x(1020);
    Complex y;
    cout << " Object x => ";
    x.ShowComplex();
    cout << " Object y => ";
    y.ShowComplex();
 
    Complex *pCom;
    pCom = &x;
    cout << "\n pCom->ShowComplex() => ";
    pCom->ShowComplex();
 
    pCom = &y;
    cout << "pCom->ShowComplex() => ";
    pCom->ShowComplex();
}
cs

▲객체 포인터 사용



내부 포인터 this

객체의 맴버함수를 호출할때 사용할 수 있는 포인터

컴파일러가 맴버변수 앞에 자동적으로 붙여주므로 생략이 가능하지만 매개변수와 이름이 같을 때 구분하기위해 사용할 수 있음


객체 간의 값 치환

클래스는 c의 구조체를 확장한 개념으로 비교는 할 수 없으나 치환은 가능함.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<iostream>
using namespace std;
 
class Complex
{
private:
    int real;
    int image;
public:
    Complex(int r = 0int i = 0);
    void ShowComplex() const;
    void SetComplex(int x = 0int i = 0);
};
 
Complex::Complex(int r, int i) : real(r), image(i)
{
}
 
void Complex::ShowComplex() const
{
    cout << "( " << real << " + " << image << "i )" << endl;
}
 
//내부포인터 this를 이용함
void Complex::SetComplex(int real, int image)
{
    this->real = real;
    this->image = image;
}
 
void main() {
    Complex x(1020);
    Complex y;
    cout << " Object x => ";
    x.ShowComplex();
    cout << " Object y => ";
    y.ShowComplex();
 
    cout << "------------------------------------ \n";
    //객체 단위로 값 치환
    y = x;
    cout << " x => ";
    x.ShowComplex();
    cout << " y => ";
    y.ShowComplex();
 
    cout << "------------------------------------ \n";
    y.SetComplex(3040);
    cout << " x => ";
    x.ShowComplex();
    cout << " y => ";
    y.ShowComplex();
}
cs

 

▲this와 객체 치환


참조에 의한 호출 방식으로도 값을 치환할 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include<iostream>
using namespace std;
 
class Complex
{
private:
    int real;
    int image;
public:
    Complex(int r = 0int i = 0);
    void ShowComplex() const;
    void SetComplex(int x = 0int i = 0);
};
 
Complex::Complex(int r, int i) : real(r), image(i)
{
}
 
void Complex::ShowComplex() const
{
    cout << "( " << real << " + " << image << "i )" << endl;
}
 
//내부포인터 this를 이용함
void Complex::SetComplex(int real, int image)
{
    this->real = real;
    this->image = image;
}
void CopyComplex(Complex *des, Complex src)
{
    *des = src;
}
void main() {
    Complex x(1020);
    Complex y;
    cout << " Object x => ";
    x.ShowComplex();
    cout << " Object y => ";
    y.ShowComplex();
 
    cout << "------------------------------------ \n";
    CopyComplex(&y, x);
    cout << " x => ";
    x.ShowComplex();
    cout << " y => ";
    y.ShowComplex();
}
cs
▲Call by Reference 치환방식



객체를 주소에 의한 호출을 사용하여 객체가 다른 것을 참조할 수 있도록 할 수 있다.


 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include<iostream>
using namespace std;
 
class Complex
{
private:
    int real;
    int image;
public:
    Complex(int r = 0int i = 0);
    void ShowComplex() const;
    void SetComplex(int x = 0int i = 0);
};
 
Complex::Complex(int r, int i) : real(r), image(i)
{
}
 
void Complex::ShowComplex() const
{
    cout << "( " << real << " + " << image << "i )" << endl;
}
 
//내부포인터 this를 이용함
void Complex::SetComplex(int real, int image)
{
    this->real = real;
    this->image = image;
}
Complex & CopyComplex(Complex &des, const Complex &src)
{
    des = src;
    return des;
}
void main() {
    Complex x(1020);
    Complex y;
    Complex z;
 
    z = CopyComplex(y, x);
    cout << " x => ";
    x.ShowComplex();
    cout << " y => ";
    y.ShowComplex();
    cout << " z => ";
    z.ShowComplex();
}
cs

 ▲모두 x를 참조하는 객체가 되는 예제


정적 멤버변수

특정 클래스의 모든 객체가 공유하는 것(전역변수 원리와 동일)

사용 조건

 

  • 정적 멤버변수는 특정 클래스 내부에 선언해야 함
  • 정적 멤버변수는 클래스 밖에서 별도로 초기화되어야 함

 정적 멤버함수에서는 this 래퍼런스 사용못함. 인스턴스 변수 사용할 수 없음. 오버라이딩 되지 않음

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<iostream>
using namespace std;
 
class StaticTest {
private:
    static int a;
    int b;
public:
    StaticTest();
    static void SetA(int new_a);
    static int GetA();
};
int StaticTest::a = 10;
 
StaticTest::StaticTest() {
    b = 20;
}
 
void StaticTest::SetA(int new_a) {
    a = new_a;
}
 
int StaticTest::GetA() {
    return a;
}
 
void main() {
    cout << " StaticTest::GetA() => " << StaticTest::GetA() << "\n\n";
 
    StaticTest s1, s2;
    s1.SetA(10000);
    cout << " s1.GetA() -> " << s1.GetA() << "\t";
    cout << " s2.GetA() -> " << s2.GetA() << "\n\n";
}
cs

▲정적 멤버변수,함수 사용 예제


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include<iostream>
using namespace std;
 
class CStud {
private:
    char name[30];
    char hphone[20];
    char email[30];
    static int cnt;
public :
    CStud(char *n= "성윤정"char *= "017-777-7777"char*= "pink@daum.net");
    ~CStud();
    void prn();
    static void prn_cnt();
};
int CStud::cnt = 0;
CStud::CStud(char *n, char *h, char *e)
{
    strcpy(name, n);
    strcpy(hphone, h);
    strcpy(email, e);
    cnt++;
}
CStud::~CStud() {
    cnt--;
}
 
void CStud::prn() {
    cout << "이름\t:" << name << endl;
    cout << "핸드폰\t:" << hphone << endl;
    cout << "이메일\t:" << email << endl;
}
 
void CStud::prn_cnt() {
    cout << "\n현재까지 등록된 인원수 : " << cnt << "\n\n";
}
 
void main() {
    CStud::prn_cnt();
 
    CStud man1("전수빈""019-9087-0975""subin@pride.com");
    man1.prn();
    CStud man2("전원지""017-9087-0975""won@pride.com");
    man2.prn();
 
    cout << "\n# 중간에 인원수를 파악합니다.";
    man2.prn_cnt();
    CStud man3;
    man3.prn();
    cout << "\n클래스의 할당된 메모리 사이즈 : " << sizeof(CStud) << endl;
    CStud::prn_cnt();
}
cs

▲정적 멤버변수 사용 이용

 


객체 배열

선언 : 클래스명 객체배열명[원소의 개수];

참조 객체배열명[인덱스].멤버변수or함수;

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<iostream>
using namespace std;
 
class Complex
{
private:
    int real;
    int image;
public:
    Complex(int r = 0int i = 0);
    void ShowComplex() const;
};
 
Complex::Complex(int r, int i) : real(r), image(i)
{
}
 
void Complex::ShowComplex() const
{
    cout << "( " << real << " + " << image << "i )" << endl;
}
 
void main() {
    Complex arr[4= {
        Complex(2,4),
        Complex(4,8),
        Complex(8,16),
        Complex(16,32)
    };
    for (int i = 0; i < 4; i++)
        arr[i].ShowComplex();
}
cs

▲객체 배열 사용 예제


 

객체 배열과 포인터 

포인터 변수에 객체 배열 인덱스를 줌으로써 사용가능

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<iostream>
using namespace std;
 
class Complex
{
private:
    int real;
    int image;
public:
    Complex(int r = 0int i = 0);
    void ShowComplex() const;
};
 
Complex::Complex(int r, int i) : real(r), image(i)
{
}
 
void Complex::ShowComplex() const
{
    cout << "( " << real << " + " << image << "i )" << endl;
}
 
void main() {
    Complex arr[4= {
        Complex(2,4),
        Complex(4,8),
        Complex(8,16),
        Complex(16,32)
    };
    Complex *pCom = arr;
    pCom->ShowComplex();
    (pCom+1)->ShowComplex();
 
}
cs

▲객체 배열을 포인터로 참조한 예제


프렌드 함수

외부 함수에서 접근하고자 할때 사용

함수 앞에 friend를 붙인다.

데이터를 보안때문에 private를 사용한것이기 때문에 허용여부를 잘 판단해야됨

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<iostream>
using namespace std;
 
class Complex
{
private:
    int real;
    int image;
public:
    Complex(int r = 0int i = 0);
    void ShowComplex() const;
 
    friend void prn(Complex *pCom);
};
 
Complex::Complex(int r, int i) : real(r), image(i)
{
}
 
void Complex::ShowComplex() const
{
    cout << "( " << real << " + " << image << "i )" << endl;
}
 
void prn(Complex *pCom) {
    for (int i = 0; i < 4; i++) {
        cout << "( " << pCom[i].real << " + " << pCom[i].image << "i )" << endl;
    }
}
 
void main() {
    Complex arr[4= {
        Complex(2,4),
        Complex(4,8),
        Complex(8,16),
        Complex(16,32)
    };
    Complex *pCom = arr;
    prn(arr);
}
cs

▲프렌드 함수 예제



개발환경 : MFC

256*256 이미지만 가능

멤버변수에 DCT한 각 픽셀값 저장후 역DCT에 사용

DCT값 출력시 해당 블록의 최대값이 255가 되도록 계산하여 블록에 출력

따로 DCT계산값을 건들이진 않음


'프로그래밍 > C++' 카테고리의 다른 글

(C++) Simple 한/영사전 예제  (0) 2016.07.09
(C++) 상속을 이용한 간단한 계산 클래스 구현  (0) 2016.07.09
(C++) 상속성  (0) 2016.07.09
(C++) 연산자 오버로딩  (0) 2016.07.09
(C++) 클래스 객체  (0) 2016.07.09

+ Recent posts