Chapter	1
Class 란 무엇인가?

class 만들기

class Myclass{   // Myclass를 정의한다.

int a;

int b;

};

Myclass my;   // Myclass변수 my를 정의한다.

위의 예에서 Myclass 는 class이고 my는 Myclass형 변수가 된다.

클래스 이름은 대문자로 시작하도록 하자. ( Myclass )

a, b는 클래스의 멤버 변수라고 한다.

my는 멤버 변수 a, b를 가지게 된다. 즉 my.a , my.b를 가진다.

class와 struct의 비교

	구조체	클래스
정의	struct mystruct{ int a; int b; };	class myclass{ int a; int b; };
변수정의	struct mystruct mys; 또는, mystruct mys;	class myclass myc; 또는, myclass myc;
필드 멤버	mys. a 와 mys. b	myc. a 와 myc. b

표에서도 알 수 있듯이 구체와 클래스는 아주 비슷하다. 그러나 구조체는 단순한 자료의 집합이고 클래스는 동작(함수)을 포함한다.

접근 지정자(공용과 전용)

구조체는 멤버가 디폴트로 공용(public)이다. 그러나 class는 디폴트로 전용(private)이다.

위의 구조체, 클래스 비교 표에서 mys. a 와 mys. b는 공용이고, myc. a 와 myc. b는 전용으로 엑세스 보호된다. 다시말하면 클래스 외부에서 멤버를 엑세스할 수 없다.

그러나 다음과 같이 하면 멤버가 공용이 되어 클래스 외부에서 접근 가능하다.

class myclass{

public:         // 멤버를 공용으로 지정

int a;

int b;

};

public 키워드 뒤에 ':'이 있음을 유의하자. private도 역시 콜론으로 마친다.

[예제]	클래스 공용 멤버 엑세스

#include<iostream.h>

#include<conio.h>

class Time{

public:          // 멤버를 공용으로 사용 가능하게 함

int hours;

int minutes;

int seconds;

};

void main(){

Time clock;

clock.hours=10;

clock.minutes=30;

clock.seconds=25;

clrscr();

cout <<clock.hours <<":" <<clock.minutes <<":"

<< clock.seconds <<endl ;

getch();

}

위의 예제에서 public:를 private으로 고치면 몇가지 에러 가 뜬다.

'Time::hours' is not accessible

'Time::minutes' is not accessible

'Time::seconds' is not accessible

여기서 영역지정자(::)가 나왔다. Time::hours 는 'Time의 멤버 변수 hours'라고 해석하면 된다. 즉 멤버 변수에 접근할 수 없다는 에러 메시지이다.

그렇다면 어떻게 전용변수에 접근할 수 있을까? 이 물음에 대한 해답은 다음 절에서 배울 맴버 함수에서 다룰 것이다.

아래의 예제는 어떻게 될까? 생각해보자.

[예제]

#include<iostream.h>

#include<conio.h>

class Time{

int hours;

public:

int minutes;

int seconds;

};

void main(){

Time clock;

clock.hours=10;

clock.minutes=30;

clock.seconds=25;

clrscr();

cout <<clock.hours <<":" <<clock.minutes <<":"

<< clock.seconds <<endl ;

getch();

}

변수가 스스로 동작하게 하는 멤버 함수

멤버 함수(member functions)를 통해서, 프로그램의 모든 전용 데이타를 엑세스할 수 있다.

변수를 출력하고자 할 때 여러분이 그 변수를 출력하지 않아도 그 변수는 스스로 출력할 것이다. 이런 마술같은 데이터 동작은 객체의 멤버 함수를 통해 모두 수행된다.

class Man {

private:           // 멤버 변수는 private로 지정( 생략해도 되나 넣는 것이 좋음)

char *name;

int age;

int height;

public:             // 공용 멤버 함수로 멤버 변수에 접근

void getname(char *s){

name=s;

}

};

getname()은 매개변수 s를 받아 멤버 변수 name에 대입한다.

Man man1 ;

man1.getname("김철수");

멤버 변수 name이 private이므로 접근 불가하지만 멤버 함수 getname()을 이용하여 간접적으로 접근할 수 있게 된다.

[예제]	공용 멤버 함수

#include<iostream.h>

#include<conio.h>

class Man{

private:

char name[20];

int age;

int height;

public:

void getname(){

cout <<"What's your name? ";

cin >>name;

}

void putname(){

cout <<"your name is " <<name <<endl;

}

};

void main(){

Man man1;

man1.getname();

man1.putname();

getch();

}

위의 예제에서 getage(), getheight(), putage(), putheight()를 추가해 보자.

다음과 같이 클래스 데이터 멤버를 초기화할 수는 없다.

class Abc{

private:

char a='g';        // 클래스 변수가 아직 정의되지 않았기 때문에

int b=33;          // 초기화할 수 없다.

float c=89.12;

public:

//생략

};

멤버 함수의 외부 정의

공용 멤버 함수 예제를 다음과 같이 할 수도 있다.

[예제]	class 간결화

#include<iostream.h>

#include<conio.h>

class Man{

private:

char name[20];

int age;

int height;

public:

void getname();           // 멤버 함수 프로토타입

void putname();

};  // 클래스 정의 끝

void Man::getname(){           // 멤버 함수 getname() 정의 부분

cout <<"What's your name? ";

cin >>name;

}

void Man::putname(){            // 멤버 함수 putname() 정의 부분

cout <<"your name is " <<name <<endl;

}

void main(){

Man man1;

man1.getname();

man1.putname();

getch();

}

클래스를 내부에 정의하면 클래스가 너무 길어진다. 따라서 클래스를 간결화 하기 위해 멤버 함수를 클래스 외부에 정의한다.

영역지정 연산자 (::)를 사용하여 클래스의 멤버 변수임을 밝힌다.

class에서 inline 함수 사용

클래스의 효율성을 개선할 수 있게 하는 또 한가지 사항이 있다. 클래스 멤버 함수에 inline을 추가하자. inline이 함수 호출을 함수 코드 자체로 확장하는 것이라고 앞에서 배웠다.

Turbo C++가 멤버 함수 코드를 성공적으로 인라인할 때 클래스 멤버 함수 실행이 보다 효율적이 된다.

아래의 예제는 위의 예제(class의 간결화)에서 inline 키워드를 추가했다.

x1행과 x2행을 유심히 보기 바란다.

[예제]	class의 인라인 사용

#include<iostream.h>

#include<conio.h>

class Man{

private:

char name[20];

int age;

int height;

public:

void getname();           // 멤버 함수 프로토타입

void putname();

};  // 클래스 정의 끝

inline void Man::getname(){           // x1행

cout <<"What's your name? ";

cin >>name;

}

inline void Man::putname(){            // x2행

cout <<"your name is " <<name <<endl;

}

void main(){

Man man1;

man1.getname();

man1.putname();

getch();

}

멤버 함수를 클래스 안에 직접 넣었다면 inlin을 명시할 필요는 없다. Turbo C++는 자동적으로 그 함수들을 인라인한다.

this 포인트 변수

this 포인프 변수란 오브젝트 자신의 시작 주소를 가리키는 포인트 변수이다.

위의 예제에서

inline void Man::getname(){

cout <<"What's your name? ";

cin >>name;

}

는 아래의 구문과 동일하다.

inline void Man::getname( ){           // x1행

cout <<"What's your name? ";

cin >>this->name;

}

const형 멤버 함수

const형 멤버 함수는 멤버 변수의 값을 임의로 수정하는 것을 막아 보호하기 위함이다.

class Man{

char *name;

public:

void getName() const{   // const형 맴버 함수

// name="철수";    x1

cout <<name;

}

};

x1행을 실행하면 에러이다.

[예제]

#include <iostream.h>

#include <conio.h>

class Man{

char *name;

public:

void setName(char *name){

this->name=name;

}

char* getName() const{

return name;

}

};

void main(){

Man man1;

man1.setName("철수");

cout <<man1.getName();

}

멤버 함수의 오버로드

멤버 함수도 오버로드할 수 있다.

[예제]

#include <iostream.h>

#include <conio.h>

class Avg{

public:

int calc(int a,int b){

return (a+b)/2;

}

double calc(double a,int b){

return (a+b)/2;

}

double calc(int a,double b){

return (a+b)/2;

}

double calc(double a,double b){

return (a+b)/2;

}

};

void main(){

clrscr();

Avg a;

cout <<a.calc(2,4) <<endl;

cout <<a.calc(1.5,4) <<endl;

cout <<a.calc(2,4.2) <<endl;

cout <<a.calc(5.2,7.4) <<endl;

getch();

}

멤버 함수의 매개변수 초기화

멤버 함수의 매개변수도 초기화할 수 있다.

[예제]

#include <iostream.h>

#include <conio.h>

class Math{

public:

int sum(int a,int b, int c=0, int d=0, int e=0){

return a+b+c+d+e;

}

};

void main(){

clrscr();

Math a;

cout <<a.sum(1,2) <<endl;

cout <<a.sum(1,2,3) <<endl;

cout <<a.sum(1,2,3,4) <<endl;

cout <<a.sum(1,2,3,4,5) <<endl;

getch();

}

[해보기]

[문제]

위의 예제에서 매개 변수의 최대값을 반환하는 멤버 함수

int max(int a, int b, int c=0, int d=0, int e=0) 과,

int min(int a, int b, int c=32000, int d=32000, int e=32000)을

추가해 보자.

[출력 예시]

max(1,2)=2

max(1,2,3)=3

max(2,5,3,8)=8

max(10,30,29,34,12)=34

min(11,21)=11

min(71,12,37)=12

...

Chapter	2
생성자 함수(Constructor)

생성자 함수는 객체가 만들어 질 때 단 한번 실행되는 함수로서 보통 멤버변수를 초기화하는 목적으로 사용된다.

class Hi{

char *say;

public:

Hi(){      // 생성자 함수

say="hi";   // 멤버 변수를 초기화하고 있다.

}

};

Hi hi;    // 객체를 만든다.

위의 예제에서 Hi()가 생성자 함수이다.

생성자 함수의 특징

●오브젝트가 만들어 질 때 자동으로 호출되는 함수

●사용자가 강제로 호출할 수 없다.

●결과형이 없다.

●리턴값이 없다.

●생성자 함수의 이름은 클래스 이름과 동일하다.

●생성자 함수는 매개변수를 가질 수 있으며 오버로드 할 수 있다.

●매개변수도 없고 함수의 내용도 없는 생성자 함수를 '디폴트 생성자 함수'라고

하며 사용자가 생성자 함수를 만들지 않으면 디폴트 생성자 함수가 있는 것으

로 취급된다.

●사용자가 생성자 함수를 만들면 디폴트 생성자는 없어진다.

●생성자 함수의 접근 지정자는 반드시 public이다.

●생성자 함수이름 뒤에 ':'(콜론) 연산자를 기재하여 멤버 변수에 초기 값을

부여할 수 있다.

●생성자 함수는 const 함수가 될 수 없다.

[예제]

#include <iostream.h>

#include <conio.h>

class Man{

char *name;

int age;

public:

Man(){

name="아무개";

age=0;

}

Man(char *name, int age):name(name),age(age){}

char* getName() const{

return name;

}

};

void main(){

clrscr();

Man man1;

Man man2("철수");

cout <<man1.getName()<<endl;

cout <<man2.getName()<<endl;

getch();

}

생성자 함수의 외부 정의

class Man{

....

public:

Man(char *name);

};

Man::Man(char *name):name(name){}

결과형이 없음에 주의 하자...

복사 생성자 함수

[예제]

#include <iostream.h>

#include <conio.h>

class Man{

char *name;

int age;

public:

Man(){

name="아무개";

age=0;

}

Man(char *name):name(name){}

char* getName() const{

return name;

}

};

void main(){

clrscr();

Man man1("철수");

Man man2(man1);          // 복사 생성자 함수 호출

cout <<man2.getName()<<endl;

getch();

}

●복사 생성자 함수를 만들지 않으면 디폴트 복사 생성자 함수가 존재하는 것으로

처리된다.

●오브젝트 생성시에 자신의 클래스형으로 이루어진 오브젝트를 인수로서

매개변수에 넘길 경우에 호출된다.

●맴버 함수 호출 시 호출되는 멤버 함수의 매개변수 자료형이 자신의 클래스형

으로 되어 있을 경우에는 이 함수가 호출될 때 임시 오브젝트가 생성되는데

이때 복사 생성자 함수가 호출된다.

●함수의 결과형이 자신의 클래스형이고 리턴값도 자신의 클래스일 때

복사 생성자 함수가 호출된다.

[예제]

#include <iostream.h>

#include <conio.h>

class Data{

int x;

int y;

public:

Data(){}

Data(int x,int y):x(x),y(y){}

Data gob(Data ob){   // 매개변수 오브젝트 생성 시 복사 생성자 호출

Data k;

k.x=ob.x*x;

k.y=ob.y*y;

return k;            // 리턴될 때 복사 생성자 호출

}

int getx(){return x;}

int gety(){return y;}

};

void main(){

clrscr();

Data a(1,2),b(2,4),c;

c=b.gob(a);

cout <<c.getx()<< endl;

cout <<c.gety()<< endl;

getch();

}

조금은 난해한 문제이군요....^^

중요한 사항이므로 잘 생각해보세요..

Chapter	3
소멸자 함수(Destructor)

소멸자 함수란 오브젝트가 소멸(메모리에서 없어짐)될 때 자동으로 호출되는 함수를 말한다. 동적으로 할당된 메모리가 있으면 소멸자 함수에서 해제하는 역할을 한다.

소멸자 함수의 특징

●소멸자 함수의 함수 이름은 클래스 이름과 같은 이름으로 기재하며 소멸자

함수는 함수명 앞에 '~'기호가 붙어야한다.

●소멸자 함수의 접근 지정자는 public이다.

●생성자 함수와 같이 결과형이 없다.

●const 함수가 될 수 없다.

●소멸자 함수는 오버로드할 수 없다.

●소멸자 함수의 호출시기는 생성자 함수 호출 시기의 역순으로 이루어진다.

●소멸자 함수는 매개변수를 가질 수 없다.

●사용자가 강제로 호출할 수 없다.

[예제]

#include <iostream.h>

#include <conio.h>

class Myclass{

int *a;

public:

Myclass(){

a=new int;

*a=5;

}

int geta(){ return *a;}

~Myclass(){

cout <<"소멸자 호출";

delete a;

}

};

void main(){

clrscr();

Myclass my;

cout <<my.geta()<< endl;

getch();

}

Chapter	4
포함 오브젝트(Embeded Object)

다른 클래스의 오브젝트를 맴버 변수로 취하고 있는 클래스를 '포함 클래스'라고

하고 이러한 클래스의 오브젝트를 '포함 오브젝트'라고 한다.

[예제]

#include <iostream.h>

#include <conio.h>

class Date{

int year, month, day;

public:

Date(){}     // x1

Date(int y, int m, int d):year(y),month(m),day(d){}   // x2

};

class Man{

char *name;

Date born;

public:

Man()     //x3

{};    // x4

Man(char *n,int y, int m, int d)   //x5

:born(y,m,d),name(n){}  // x6

};

void main(){

clrscr();

Man man1;      // x7

// x8

Man man2("명호",1974,9,16);  //x9

getch();

}

Man 클래스의 멤버 변수 중에 Date형 오브젝트 변수가 있다..

이놈이 포함 오브젝트이다..

먼저 실행 순서를 보자..

x7 -> x3 -> x1 -> x4 -> x7 -> x8

x9 -> x5 -> x2 -> x6 -> x9

born이 만들어져야만 man1이 만들어진다는 점만 이해하면 크게 어려울 게 없다.

[해보기]

[문제]

학생클래스는 성적과 생년월일이 있다.

다음 클래스를 완성하라.

class Date{

int year;

int month;

int day;

생성자 함수 작성

};

class Sungjuk{

int kor;

int eng;

int math;

생성자 함수 작성

};

class Student{

char *name;

Date born;

Sungjuk middle;

생성자 함수 작성

출력 함수 작성

};

Chapter	5
오브젝트 배열(Object Array)과 오브젝트 동적 할당

오브젝트 배열

뭐 오브젝트의 배열이다.. 별시리 없다.

[예제]

#include <iostream.h>

#include <conio.h>

class Man{

char *name;

public:

Man(){};

Man(char *n):name(n){}

char* getName(){return name;}

};

void main(){

clrscr();

Man teacher[3];  // 오브젝트 배열, 디폴트 생성자 호출

Man student[10]={Man("철수"),Man("영희")};

// 원소 2~9는 디폴트 생성자 호출

cout<< student[1].getName();  // "영희"가 출력 된다.

getch();

}

오브젝트 동적 할당

이것도 마찬가지 별시리 없다.. 오브젝트를 힙에다 할당한다.

[예제]

#include <iostream.h>

#include <conio.h>

class Man{

char *name;

public:

Man(){};

Man(char *n):name(n){}

char* getName(){return name;}

void  setName(char *n){ name=n;}

};

void main(){

clrscr();

Man *teacher =new Man("서선생");   //할당

Man *student =new Man[10];        // 오브젝트 배열을 할당

cout <<teacher->getName() <<endl;

student[3].setName("박대종");

cout <<student[3].getName();

getch();

}

[해보기]

[문제]

위 예제는 메모리 해제하는 부분이 빠져있다..

결국 좋은 습관이 아니다.

해제하는 코드를 추가하는 좋은 습관을 가져보자..

[출력 예시]

^^

[해보기]

[문제]

오브젝트 2차원 배열을 만들어보자...동적 할당할 것.

위 예제에서 학생 오브젝트를 2차원 배열로...

Man student[8][50];

한 학년은 8학급이고 총원 50명이다...

[출력 예시]

T.T

Chapter	6
static

static 맴버 변수

오브젝트를 만들지 않아도 사용할 수 있는 변수. '클래스 변수'라고도 한다.

모든 오브젝트가 공유하는 변수이다.

class Hi{

static int hi;

...

};

int Hi::hi=10;  <--static 변수는 꼭 초기화를 해야 하며, 클래스 밖에서 한다.

[예제]

#include <iostream.h>

#include <conio.h>

class Man{

public:

static int count;   // static 변수

char *name;

Man(char *name){

this->name=name;

count++;             // count를 1 증가시킨다.

}

};

int Man::count=0;

void main(){

clrscr();

Man man1("주재진");

Man man2("박은속");

cout <<man1.count <<endl;

cout <<man2.count <<endl;

Man man3("Mr.Seo");

cout <<Man::count <<endl;    // 클래스 변수라고도 한다.

cout <<man1.count <<endl;

getch();

}

this 포인터

위 예제의 클래스 Man의 생성자 함수를 보자..

Man(char *name){

this->name=name;

count++;

}

사실은 매개 변수에 this가 숨어 있다.

Man(Man *this , char *name){

this->name=name;

this->count++;             // 그래서 이렇게 되는 것이다.

}

★ 그러나 static 멤버 함수는 this가 없다.

static 멤버 함수

●this 포인터 변수를 가지고 있지 않다.

●this를 가지고 있지 않으므로 멤버 변수에 접근할 수 없다.

●static 변수나 다른 static 멤버 함수는 호출할 수 있다.

●일반 멤버 함수에서는 static 함수를 마음대로 호출할 수 있다.

●객체를 만들지 않고도 호출할 수 있다.

class Hi{

public:

static void say(){

cout <<"하이여~~";

}

...

};

Hi hi;

호출 할 때는 Hi::say(); 또는 hi.say();

[예제]	진실은 무섭다.

#include<iostream.h>

#include<conio.h>

class Hi{

public:

static void say_hi(){

cout <<"하이여~~"<< endl;

}

static void say_lie(){

cout <<"정말 이쁘시네요.....!!!"<< endl;

}

static void say_truth(){

cout <<"뻥이야~~~~~~"<< endl;

}

};

void main(){

clrscr();

Hi::say_hi();

Hi::say_lie();

Hi::say_truth();

getch();

}

[예제]

#include<iostream.h>

#include<conio.h>

class Hi{

int a;

static int b;

public:

static void say_hi(){

cout <<"하이여~~"<< endl;

// a=1;     멤버 변수에 접근할 수 없다.

b=2;       // static은 된다.

}

void say_lie(){

cout <<"정말 이쁘시네요.....!!!1"<< endl;

}

void say_truth(){

cout <<"뻥이야~~~~~~"<< endl;

}

};

int Hi::b=1;   // 여기를 생략하면 어떻게 될까?

void main(){

clrscr();

Hi i;

Hi::say_hi();

i.say_lie();

i.say_truth();

i.say_hi();

getch();

}

[예제]

#include<iostream.h>

#include<conio.h>

class Math{

public:

static int max(const int x, const int y){

return x>y?x:y;

}

static int min(const int x, const int y){

return x<y?x:y;

}

static int avg(const int x, const int y){

return (x+y)/2;

}

};

void main(){

clrscr();

cout <<Math::max(5,7) <<endl;

cout <<Math::min(5,7) <<endl;

cout <<Math::avg(5,7) <<endl;

getch();

}

static 함수...좋죠?

위의 Math 클래스는 아주 좋은 예제이다.

static 멤버 함수를 언제 사용해야 하는지 확실히 알아야 한다.

Chapter	7
friend (친구야, 내가 니 시다바리가?)

friend 함수

일단 예제를 보자.

[예제]

#include<iostream.h>

#include<conio.h>

class JJang{

private:

int a;     // 일반적으로 클래스 밖에서 접근 불가능하다.

int b;

public:

void print(){

cout <<a <<'\t' <<b <<endl;

}

friend void sidabari();   // 여기가 친구 함수 Prototype. 친구로 등록한다.

};

void  sidabari(){

JJang o_sung;

o_sung.a=10;     // private 멤버 함수에 접근하고 있다.

o_sung.b=20;

o_sung.print();

}

void main(){

clrscr();

sidabari();

getch();

}

일반 함수를 클래스의 친구로 등록할 수 있다.

그래서 친구 함수가 클래스의 모든 멤버에게 접근하게 한다.

친구 함수는 클래스의 멤버 함수가 아니라 일반 함수임을 주목하자.

prototype 선언 위치는 중요하지 않다.

[예제]

#include<iostream.h>

#include<conio.h>

class Zang{

private:

friend void sidabari(Zang &);

int a;

int b;

public:

Zang(int a, int b):a(a),b(b){}

};

void  sidabari(Zang &k){

cout <<k.a <<'\t' <<k.b;

}

void main(){

clrscr();

Zang o_sung(10,20);

sidabari(o_sung);

getch();

}

friend class

friend 함수와 비슷하다. 단지 클래스를 친구로 등록한다.

[예제]

#include<iostream.h>

#include<conio.h>

class Zang{

friend  Sidabari;   // Sidabari 클래스를 친구 클래스로 등록

int a;

int b;

public:

void print(){

cout <<a <<'\t' <<b <<endl;

}

};

class Sidabari{   // Zang 클래스의 멤버를 마음껏 다룬다.

int a;

int b;

public:

Sidabari(int a, int b):a(a),b(b){}

void setZang(Zang &k){

k.a=a;

k.b=b;

}

};

void main(){

clrscr();

Zang o_sung;

Sidabari dong_gun(10,20);

dong_gun.setZang(o_sung);

o_sung.print();

getch();

}

Chapter	8
상속(Inheritance)

부모로부터 물려받는 것을 상속이라 한다.

예를 들어 설명하자면,

사각형은 도형을 상속한다.

버스는 자동차를 상속한다.

'상속'을 '파생'이라고도 한다.

클래스에서도 상속이 존재한다.

클래스의 상속

class Parent{    // 부모 클래스 or 상위 클래스 or 기초(Base) 클래스

int a;

int b;

public:

void f(){}

};

class Child : 파생유형 Parrent{

// 자식 클래스 or 하위 클래스 or 파생(Derived) 클래스

int c;

int d;

public:

void g(){}

};

☆Child의 멤버 변수: a, b, c, d

☆Child의 멤버 함수: f(), g()

--->Child클래스는 부모 클래스의 모든 것을 가진다.

(생성자, 소멸자, 프렌드 함수 제외-->당근 )

파생유형에는 private, public, protected가 있다.

파생유형은 Child클래스와는 상관없고, Child클래스를 상속하는 다른 클래스와 관계있다. Woops~

자식이 부모 멤버로 접근

class Parent{

private:

int a;

public:

int b;

void f(){a=1;}

};

class Child : 파생유형 Parrent{

private:

int c;

public:

void g(){

a=1;   // x1

b=1;   // x2

f();    // x3

}

};

x1행을 보자.. a는 부모의 멤버 변수이다.

근데 접근 지정자가 private이므로, 접근 불가이다. 즉 에러....

x2행을 보자.. b는 부모의 멤버이다..

접근 지정자는 public이므로 접근 가능하다.. 에러 없음...

x3행도 f()가 public이므로 접근 가능하고, 에러가 없다...

부모는 자식을 가리킬 수 있다.. 그러나...

[예제]

#include <iostream.h>

#include <conio.h>

class Man{

char *name;

char *sex;          // 성(性), 다른 뜻 없음

public:

Man(char *n, char *s):name(n),sex(s){}

void print(){

cout <<name <<" " <<sex <<endl;

}

};

class Student : public Man{

int rank;

int IQ;

public:

Student(char *n, char *s,int r, int i):Man(n,s),rank(r),IQ(i){}

// 부모 생성자를 맨 먼저 호출

void print(){   //  Override

Man::print();    // 부모의 멤버를 호출한다.

cout <<rank <<" " <<IQ <<endl;

}

};

void main(){

clrscr();

Man *man1=new Student("철수","남",1,150);   // 부모변수가 자식을...

Student *man2=new Student("하리수","식별불가",2,100);

man1->print();   // x1행

man2->print();   // x2행

getch();

}

x1행에서 printf()는 부모의 것을 호출한다.

x2행에서 printf()는 자식의 것을 호출한다.

자식이 부모가 가지고 있는 것과 같은 것을 가지는 것을 override라고 한다.

★부모 변수로 자식의 멤버를 호출할 수 없는 걸까? 답: 있다.

그럼 어떻게? 답: virtual (나중에)

생성과 소멸

닭이 먼저? 알이 먼저?

자식이 생성되려면 부모가 먼저 생성되어야 한다.

소멸은 반대로...

[예제]

#include <iostream.h>

#include <conio.h>

class Man{

public:

Man(){

cout <<"디폴트 부모 생성자 호출" <<endl;

}

Man(int a){

cout <<"부모 생성자 호출" <<endl;

}

};

class Student:public Man{

public:

Student(){   // 디폴트 부모 생성자 호출

cout <<"자식 디폴트 생성자 호출" <<endl;

}

Student(int a){    // 디폴트 부모 생성자 호출

cout <<"자식 생성자1 호출" <<endl;

}

Student(double b):Man(1){   // x1 부모 생성자 호출

cout <<"자식 생성자2 호출" <<endl;

}

};

void main(){

clrscr();

Student *man1=new Student;

Student *man2=new Student(1);

Student *man3=new Student(1.0);

getch();

}

x1: 부모 생성자 호출 시 자식의 생성자 함수 이름 뒤에 ':'을 기재하고 생성자 함수를 기재한다.

오버라이드(Override)

부모의 멤버 변수나 함수가 자식에게도 있는 것을 오버라이드라 하고,

부모의 멤버를 호출하기 위하여 영역 지정 연산자(::)를 사용한다.

[예제]

#include <iostream.h>

#include <conio.h>

class House{

public:

int door;

char *color;

void clear(){

cout <<"집을 청소합니다."<< endl;

}

};

class Apart:public House{

int door;  // 멤버 변수 오버라이드

public:

void clear(){    // 멤버 함수 오버라이드

cout <<"아파트를 청소합니다."<< endl;

door=1;

House::door=2;   // 부모 변수 호출

}

void print(){

cout <<door <<" " <<House::door <<endl;

}

};

void main(){

clrscr();

Apart *a1=new Apart;

a1->clear();          // 내꺼 호출

a1->House::clear();  // 부모 멤버 함수 호출

a1->print();

delete a1;

getch();

}

파생유형  (손자에게만 영향을 미친다.)

class Grand{

private:

int g;

public:

int gg;

};

class Parent : 파생유형 Grand{    // x1

private:

int p;

public:

int pp;

};

class Child : public Parent{

private:

int c;

public:

int cc;

void f(){}

};

Child k;

x1행의 파생유형은 public, private, protected 중 아무거나 올 수 있다.

①public: Grand를 public으로 다루겠다는 의미

Child에서 Grand의 공용 멤버에 접근 가능하다.(gg=10)

클래스 외부에서 Grand 공용 멤버에 접근 가능하다.(k.gg=10)

②protected: Grand를 protected로 취급하겠다.

Child에서 Grand의 공용 멤버에 접근 가능하다.(gg=10)

클래스 외부에서는 Grand 공용 멤버에 접근 불가하다.

③private: Grand를 private으로 취급하겠다는 의미.

Child에서 Grand의 모든 멤버에 접근 불가하다.

클래스 외부에서도 Grand 공용 멤버에 접근 불가하다.

위의 예로 연습해보자.

Chapter	9
가상 함수(virtual function)

다형성(polymorphism)

형태가 다양하다는 뜻이다. 오버라이드 함수 앞에 'virtual' 키워드를 기재하여 부모 오브젝트 변수를 사용하여 자식 오버라이드 멤버 함수를 호출할 수도 있고, 선조 멤버 함수를 호출할 수도 있다.

[예제]

#include <iostream.h>

#include <conio.h>

class Parent{

public:

virtual void say(){   // virtual 함수

cout <<"부모" <<endl;

}

};

class Child:public Parent{

public:

void say(){

cout <<"자식" <<endl;

}

};

void main(){

clrscr();

Parent *p=new Parent;

p->say();

Child *c=new Child;

c->say();

Parent *pc=new Child;

pc->say();

getch();

}

순수 가상 함수 (추상 함수)

virtual 결과형 func()=0;

이것이 가상 함수다. 정의 부분이 '0'으로 되어있다.

즉 정의 부분이 없다. 정의 부분이 없기 때문에 오브젝트화 될 수 없다.

순수 가상 함수를 포함한 클래스를 추상 클래스(abstract class)라고 한다.

[예제]

#include <iostream.h>

#include <conio.h>

class Parent{        // 추상 클래스

public:

virtual void say()=0;     // 순수 가상함수

};

class Child:public Parent{

public:

void say(){

cout <<"자식" <<endl;

}

};

void main(){

clrscr();

//   Parent *p=new Parent;  추상 클래스는 오브젝트화 될 수 없다.

Parent *pc=new Child;

pc->say();

getch();

}

추상 함수를 사용하는 목적은 일종의 약속을 만드는 것이다.

추상 클래스를 상속한 클래스는 추상 함수를 오버라이드하여 정의 부분을 기재하여야 한다. 그래서 모든 자식 클래스는 이 추상 함수를 사용하게 된다.

약속을 지키자.

Chapter	10
다중 상속(Multiple Inheritance)

여러 클래스를 상속하는 것을 다중 상속이라 하며,

다중 상속을 한 놈은 부모가 여러 개이다.

[예제]

#include <iostream.h>

#include <conio.h>

class AAA{

public:

void f(){

cout <<"AAA" <<endl;

}

};

class BBB{

public:

void g(){

cout <<"BBB" <<endl;

}

};

class CCC:public BBB,public AAA{  // 다중 상속

public:

void h(){

cout <<"CCC" <<endl;

}

};

void main(){

clrscr();

CCC c;

c.h();

c.g();

c.f();

getch();

}

다중 상속의 오버라이드

부모가 공통된 멤버를 가지고 있을 때...

[예제]

#include <iostream.h>

#include <conio.h>

class AAA{

public:

void f(){

cout <<"AAA" <<endl;

}

};

class BBB{

public:

void f(){

cout <<"BBB" <<endl;

}

};

class CCC:public BBB,public AAA{  // x1행, 다중 상속

public:

void f(){    // 오버라이드

cout <<"CCC" <<endl;

}

};

void main(){

clrscr();

CCC c;

c.f();

c.AAA::f();  // AAA의 f() 호출

c.BBB::f();  // BBB의 f() 호출

getch();

}

별시리 어려울 게 없다.

x1행의 public AAA를 private AAA로 바꾸면 어떻게 될까?

다중 상속의 구조

AAA--- BBB---DDD

AAA---CCC---DDD

클래스 BBB는 AAA를 상속하고, CCC도 AAA를 상속하며

DDD는 BBB와 CCC를 상속한다.

[예제]

#include <iostream.h>

#include <conio.h>

class AAA{

public:

void f(){

cout <<"AAA" <<endl;

}

};

class BBB:public AAA{

public:

void f(){

cout <<"BBB" <<endl;

}

};

class CCC:public AAA{

public:

void f(){

cout <<"CCC" <<endl;

}

};

class DDD:public BBB,public CCC{

public:

void f(){

cout <<"DDD" <<endl;

}

};

void main(){

clrscr();

DDD d;

d.f();

d.BBB::f();

d.CCC::f();

// d.AAA::f();    x1행

getch();

}

x1행에서 에러가 발생한다. 이런 구조에서는 최상위 클래스의 멤버를 호출할 수 없다.

그럼 어떻게 AAA::f()를 호출 할 수 있을까?

[해보기]

[문제]

위의 예제에서 AAA::f()를 main()에서 호출하는 방법을 모색하여라.

[출력 예시]

AAA

--------

☞ DDD::f()의 정의 부분을 삭제하면 어떻게 되는가?

Chapter	11
연산자 오버로딩(Operator Overloading)

overlord, overload, override 의 차이점

①overlord: 저그(zerg)의 정신적 지주, 업그레이드하면 빠르다.

가끔 수송도 한다. (중요한 내용 아님.)

②overload: 같은 이름으로 함수를 여러 개 만드는 것을 말한다.

③override: 부모의 멤버를 재정의 하는 것을 말한다.

friend 함수로 오버로딩

오버로드 연산자 함수를 friend 함수로 설정한다.

[예제]

#include <iostream.h>

#include <conio.h>

class Su{

int a;

public:

Su(){}

Su(int a):a(a){}

int geta(){

return a;

};

friend Su operator+(Su &, Su &y);  // 프랜드로 설정한다.

};

Su operator+(Su &x, Su &y){

Su temp;

temp.a=x.a+y.a;    // private 멤버도 접근할 수 있다.

return temp;

}

void main(){

clrscr();

Su su1(10),su2(20),su3;

su3=su1+su2;

cout <<su3.geta();

getch();

}

클래스의 멤버로 정의

클래스의 멤버로 정의할 수도 있다.

[예제]

#include<iostream.h>

#include<conio.h>

class Data{

int x;

public:

Data() {x=0;}

Data(int i) {x=i;}

int getx(){return x;}

Data operator+(Data ob);

Data operator*(Data ob);

Data operator-(Data ob);

};

Data Data::operator+(Data ob){  // x1행

return x+ob.x;

}

Data Data::operator*(Data ob){

return x*ob.x;

}

Data Data::operator-(Data ob){

return x-ob.x;

}

void main(){

clrscr();

Data ob1(3), ob2(5),ob3;

ob3=(ob1+ob2)*ob1-ob2;    // x2행

cout<<"(ob1+ob2)*ob1-ob2= " <<ob3.getx() <<endl;

getch();

}

x1행의 Data operator+(Data ob)을 보자.

여러분은 멤버 함수에 this가 숨어 있다는 것을 이미 알고 있다.(찔리면 안됨)

따라서 다른 말로 Data operator+(Data *this, Data ob)가 된다.

멤버로 정의할 때는 매개 변수가 하나임을 이해하자.

Data Data::operator+(Data ob){

return x+ob.x;  // 결과 형이 Data 인데 int를 리턴하고 있다.

}

가능한가?

생성자 함수중에 Data(int i)가 있어서 가능하다.

임시 객체가 생김을 알아야 한다.

x2행를 아래와 같이 수정하면 어떻게 될까?

ob3=(ob1+5)*ob1-ob2;

결과는 같다.. Woops~~~~

이해가 되지 않는다면 생성자와 복사 생성자를 완전히 이해하지 못했다는 말이 된다.

Chapter	12
파일 스트림(File Stream)

ifstream: 입력에 관련된 스트림

ofstream: 출력에 관련된 스트림

fstream: 읽거나 출력하거나 하는 모든 파일을 다루는 스트림

순차 파일에 쓰기

[예제]

#include<iostream.h>

#include<fstream.h>

#include<conio.h>

void main(){

clrscr();

ofstream of("test.dat");

of <<"hi\n";

of <<"good\n";

of <<"file output is easy..\n";

getch();

}

of.close() ---- 파일을 닫아 준다.

of.fail() ---- 파일을 열지 못하면 0이 아닌 값을 반환

of.eof() ---- 파일 포인터가 파일의 끝에 와있으면 0이 아닌값을 반환

순차 파일로부터 읽기

[예제]

#include<iostream.h>

#include<fstream.h>

#include<conio.h>

void main(){

clrscr();

ifstream iif("test.dat");

char s1[255],s2[255],s3[255];

iif.getline( s1,255,'\n'); // 한 라인씩 읽기

iif.getline( s2,255,'\n');

iif.getline( s3,255,'\n');

cout <<s1 <<endl;

cout <<s2 <<endl;

cout <<s3 <<endl;

getch();

}

iif.get(문자변수) ---- 파일에서 한 문자를 읽어 변수에 기억시킴

iif.get(문자열 변수, 읽을 글자수+1, '문자')-- 문자열 변수에 글자 수만큼 읽는다.

읽지 못해도 문자 앞까지 읽는다.]

iif.getline(문자열 변수, 읽을 글자수+1, '\n') ---- 한 줄씩 읽는다.

기타 등등 있으나 요기까지....

수고^^