티스토리 뷰


C언어의 특징


C언어가 어떤 특징을 가지는지 일상 생활에서 찾아볼 수 있다.

편의점을 예로 들어, 편의점에는 계산대와 물품들이 나열되어 있는 진열대로 구분할 수 있다.

이때 손님들은 자기가 원하는 물품들을 진열대에서 골라 계산대에서 결제후 가져가는 형태이다.

C언어도 이와 같다고 생각하면 된다. 데이터들이 진열대에 나열되어 있고, 필요한 데이터들을 선택 후,

계산대에서 체크후, 데이터들을 가지고 나가면 된다. 이는 매우 자율도가 높다고 볼 수 있다.

단점이 있다면 도난의 위험이 있다는 것이다. 그리고 손님이 원하는 물건의 위치가 바뀔 때 마다 손님은 물건의

위치를 다시 찾아야 한다는 단점이 있다.


C++의 특징

    

C++언어의 특징을 일상 생활에서 찾아보면 은행과 같다고 생각할 수 있다.

은행 창구가 있고, 그 창구에 안의 사람이 서비스를 제공해주는 

창구가 있고, 그 창구에 한 사람이 존재 이 한사람이 서비스를 제공해주기 위해 창구 안에 존재하는

데이터들의 정보를 전부 알고 있다.

그리고 손님들은 번호표를 뽑아서 순서대로 서비스를 받는다.

단점: 속도가 떨어진다. 자율도가 낮다.


객체지향이란?


C언어에서는 모듈이라는 개념을 제공했다. 모듈은 함수의 집합체로서 코드로 국한된 단위,

하지만 구조체와 같이 데이터를 정의하고 관리하는 문법과는 별개로 사용되었기 때문에 어떤 정보를 표현함에 있어서 일관성이 떨어졌다.


C++ 에서는 정보의 독립성과 일관성을 유지할 수 있도록,

데이터를 정의하는 구조체나 해당 구조체를 사용하는 함수를 하나로 표현할 수 있도록 하였다.


객체 지향 용어

    

인터페이스

기능을 어떻게 구현했는지 몰라도 그 기능을 사용할 수 있도록 제공되는 함수


메소드

클래스 내부에서 사용되는 함수


멤버 데이터


객체 지향에 대해 자세히 알아보려 한다. 우리가 한번 생각해 보자. 


                                                         



커피를 마시려면 컵에 직접 커피 가루, 프림, 설탕을 넣어 커피를 만드는 과정이 있고,

커피 머신 버튼을 눌러 커피를 나오게 하는 방법이 있다. 이때 객체 지향에 해당하는 것이 바로 커피 기계이다.

우리가 커피 머신을 이용해 커피를 마시는 방법은 기계 내부에서 커피가 어떻게 만들어지는지 자세히 모르지만

버튼이라는 기능(인터페이스)을 이용해 커피가 나오게 된다. 기계 내부에서 커피가 만들어지는 과정이 메소드이고,

커피 가루, 프림, 설탕은 멤버 데이터이다.


클래스의 구조

    

struct People {

char name[10];

int age;

double height;

};


void AddPeople ( People *p){

scanf("%s", p -> name);

scanf("%d", &p -> age);

scanf("%lf", &p -> height;);

}


void main () {

People data;

AddPeople(&data);

}


위의 코드는 C언어 작성한 것이다. 이 코드를 C++코드 형식으로 바꾼것이 바로 아래에 오는 코드이다.


class People{

private:

char name[10];

int age;

double height;


public:

void AddPeople() {

scanf("%s",name);

scanf("d",&age);

scanf("%lf",&height);

}

};


void main (){

class People Data;

data.AddPeople();

}


C와 C++의 차이를 발견할 수 있다. 바로 포인터의 유무이다.


class student {     //클래스 명

private :   //멤버 변수

int age;

public :    //멤버 함수

student (){

age = 0;    //객체생성자

}

~student (){

                        //객체파괴자

}

void Setage(int a){     //인터페이스

age = a;

}

int GetAge(){

return age;

}        

};


객체 생성자


클래스와 동일한 이름을 가진 함수이다. 객체 생성시 자동으로 호출된다.

클래스 내의 멤버 변수를 초기화 해주는 함수이다.

인자만 다른 동일한 이름의 함수가 여러 개 존재 가능(인자란 매개변수를 의미)

함수의 반환형이 존재하지 않는다.


class Student {

private :

int age;

public :

Student(){      만약 매개변수가 없으면 0으로 초기화

age = 0;

}

Student(int a){     만약 매개변수가 있으면 a로 초기화

age = a;

}

}


객체 파괴자


생성되었던 객체가 더 이상 사용되지 않을 때 호출되는 함수이다.

클래스 명 앞에 ~가 붙은 이름을 가진다.(NOT 연산자와 동일하다.)

인자가 없는 단 하나의 객체 파괴자만 가질 수 있다.

생략이 가능하다.

객체가 파괴되는 시점을 알 수 없으므로 파괴자 함수를 명시적으로 호출할 수 없다.


class Student {

private:

               int age;

public :

~Student(); //사용시 Student:: ~ Student(){printf("End");}

}


접근 제한자(함수를 많이 만들려고 유도하는 것 - 변수 변화에 대처하기 위해 함수를 만들어야햌ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ)


외부 클래스에서 해당 클래스의 멤버 변수와 멤버 함수의 사용 여부를 결정하기 위해 사용하는것이 

접근 제한다.

멤버의 앞에 private, public, protected 키워드와 :를 함계 사용하여 명시하며,

클래스에서 어떤 접근 제한자도 명시하지 않을 경우에는 기본적으로 멤버가 private 권한을 가진다.


private

외부 클래스에서 해당 클래스 멤버의 접근이 불가능하며, 클래스 내에서만 사용할 수 있다.

C++에서는 벙조 은닉을 위하여 기본적으로 멤버 변수가 private 권한을 갖도록 선언한다.


public

외부 클래스에서 해당 클래스 멤버의 접근이 가능하다.

주로, 멤버 변수들을 외부 클래스에서 사용할 수 있도록 하는 인터페이스들을 public 으로 선언한다.


class Student {

private :

int age;

public :

Student(){

age = 0;

}

void Setage(int a){

age = a;

}

};


void main () {

Student data;

data.age = 5;       //오류 발생 외부 클래스가 private에 접근하지 못한다.

data.Setage(5);     //외부 클래스가 public에 접근하기에 가능하다.

}


THIS 포인터


struct MyData{

int data;

};


void SetMyData(MyData *parm_temp, int parm_data){

parm_temp -> data =  parm.data;

}


void main (){

MyData temp;

temp.data = 5; // 직접 접근


SetMyData(&temp, 5);    //간접 접근

}


class MyData{

private :

int data;

public :

void SetMyData(int parm_data){

data = parm_data;

}

};


this 포인터는 현재 활성화된 객체의 주소를 가지고 있는 포인터이다.


클래스 명 * const this


클래스 내부에서 현재 작업 중인 객체의 멤버 변수나 멤버 함수에 접근하기 위해 컴파일러가 

내부에서 선언한다.


class MyData{

private :

int data;

public :

void SetMyData(int parm_data){

MyData * const this;    //숨겨진 코드

this -> data = parm_data;   //컴파일러 해석

data = parm_data;

}

};


THIS 포인터의 상수화


const 키워드를 함수 반환 값 앞에 명시하는 경우 반환 값이 상수화

const 키워드를 함수 선어 후 뒤에 명시하면 this 포인터가 가리키는 값이 상수화


class MyData{

private :

int data;

public :

void SetMyData(int parm_data) const{    //const 멤버함수라 한다.

const MyData * const this;

this -> data = pram_data;   //에러난다. 오직 읽기만 가능하다. 변수의 값 변경 불가능

}

}


상속


웹 페이지에서와 같이 프로그램을 작성할 때에도 많은 코드의 중복이 발생한다.

코드의 중복은 비슷한 기능을 하는 클래스의 코드를 그대로 복사해서 사용하기 때문에 많이 발생한다. 

따라서 웹 페이지의 링크와 같은 개념을 도입하여 중복된 코드를 쓰지 않도록 하는 것이 상속이다.

상속 문법을 사용하면 동일한 코드가 명시한 곳에 있으니 이 클래스는 해당 클래스와 기본적으로 동일하다 는 뜻으로 컴파일러가 판단한다.


class A{

int Add(int a, int b){

return a + b;

}

};

class B:public A{

};

void main(){

A a;

int num1 = a.Add(3,5);    // num1은 8로 출력


B b;

int num2 = b.Add(1,4);    // num2는 5로 출력된다.


}


상속 등급


부모 클래스를 어떤 등급으로 상속하느냐에 따라 자식 클래스에서 부모 클래스 멤버에 접근할 수 있는 

등급이 달라진다.

private 등급은 접근할 수 없다.

protected는 사용에 따라 접근 방식이 달라진다.

대부분의 경우 public 상속 등급을 사용한다. public 등급은 언제든지 접근이 가능하다.


class Parent {

private :

int debt;

protected :

int property;

public :

int GetDebt();

int GetProperty();

};


오버로딩


C++에서는 함수 명만으로 함수를 구분 짓는 C에서와는 다르게 인자의 갯수나 인자의 데이터 형으로 달리하여

동일한 이름의 함수를 사용할 수 있도록 제공한다. 이것을 함수 오버로딩이라 한다.


단 함수의 반환형만 다른 경우에는 동일한 함수로 인식되기 때문에 주의해야 한다.



오버라이딩


클래스간의 상속 관계에서 상위 클래스에 존재하는 함수를 하위 클래스에서 기능을 재정의하여 사용하는 것을 오버라이딩이라고 한다.

오버라이딩은 오버로딩과 달리 함수의 이름, 인자의 개수, 인자의 데이터 타입이 정확히 일치해야 한다.






Allocation & Instance


할당 (Allocation)

메모리를 할당한다.


struct People data;

int num = 5;

char arr[10];


인스턴스 (Instance)

메모리를 할당(allocation)함과 동시에 객체를 초기화한다.


class Student{

Student(){

}

};

Student data;


객체의 동적 할당


클래스를 사용하기 위해 동적으로 메모리를 할당하고 해제하는 방법에는 두 가지 존재한다.

첫번째 방법은 C언어와 같은 malloc - free 함수를 이용하는 것이고,

두번째 방법은 new - delete 연산자를 이용하는 것이다.


malloc - free 함수


malloc과 free 함수를 이용하면 동적으로 메모리를 할당하고 해제할 수 있지만

객체 생성자와 객체 파괴자 정상적으로 수행되지 않기 때문에 클래스 객체 생성시에는 사용하지 않는다.


struct People *p = (People *) malloc (sizeof(People));

class Student *p = (Student *) malloc (sizeof(Student));


에러는 아니지만 클래스가 정상적으로 생성되지 않는다.


new - delete 연산자


클래스 객체를 동적으로 할당하고 초기화하기 위해 사용되는 연산자로서, new연산자를 사용하여 객체를

생성하면 해당 객체는 Heap영역에 할당된다. new 연산자로 할당한 메모리는 반드시 delete 연산자로

해제해줘야 한다.


Student *p = new Student();    //객체가 할당되고 student 클래스의 객체 생성자가 호출


delete p;                                   //new 연산자로 할당된 메모리가 해제되며 객체 파괴자가 호출


int *p_num = new int [5];

delete[] p_num;

//기본 데이터 형도 new 연산자를 사용하여 할당할 수 있으며 배열 형 메모리를 

할당하는 경우에는 해제시에 delete 옆에 [ ] 를 명시해야 한다.


Namespace 


C++ 에서 함수나 변수의 이름이 중복되는 것을 막아주고, 코드의 가독성을 높이기 위해 Namespace라는 

문법을 제공한다.











    













다형성


class A {

protected : 

int a.;

int b;

};


class B : public A {

protected;                    C++ 에서는 캐스팅 작업을 하지 않고 자식 클래스를 부모

int c;                             클래스의 포인터로 가리킬 수 있다.

};


void main (){

B temp;

A *p = & temp;

}


다형성처럼 암시적인 호출에 걸렸을 경우 모호성 발생


class A {

public :

void Test() {

printf("하품\n");

}

};


class B : public A {

public :

void Test() {

printf("경찰\n");  

}

};


void main () {

B temp;

A *p = & temp;

p -> Test();

}


class A {

public :

virtual void Test() {

printf("하품\n");

}

};


class B : public A {

public :

void Test() {

printf("경찰\n");  

}

};


void main () {

B temp;

A *p = & temp;

p -> Test();

}


virtual 을 사용하게 되면 부모 우선이 아닌 자식이 우선이 된다. 


애완 동물 관리 프로그램








댓글