본문 바로가기
코스웨어/11년 내장형하드웨어

[내장형]이상만 111115 C++ 수업정리

by 알 수 없는 사용자 2011. 11. 15.
728x90
반응형
수업시간 진도순서대로 정리하였습니다!!

클래스 포인터라는것은 구조체 포인터와 같습니다

.-DDEBUG 사용
: -DDEBUG를 사용하여 컴파잉시 지정해둔 곳을 호출하여 사용 할 수 있습니다 먼저 등록하는 방법은 아래와 같습니다 

#ifdef
                cout << "hello\n";
#endif


#if부터  #end까지의 코드를  컴파일시 -DDEBUG로 옵션을 주면 적용이됩니다 기본 컴파일시에는 적용이 되지않습니다 즉 걍 컴파일시에는 메세지가 출력되지 않지만 옵션 적용시 hello가 출력됩니다

실행은 기본옵션에 -DDEBUG를 추가 합니다

g++ -o main main.cpp -DDEBUG


hello가 출력되는것을 확인 할 수 있습니다

참고>> -D 옵션 (외부에서 #define 을 정의하는 옵션입니다)


-D 옵션을 알아보겠습니다


--------------------------------------------------------------

  #include <stdio.h>


  int main(int argc,char** argv)

  {


    #ifdef   TEST

    printf("Hello, World\n");


    #else


    printf("Hello, New World\n");


    #endif


     return 0;

  }

--------------------------------------------------------------


소스에서 보듯이 TEST 가 정의되어 있으면 Hello, World 를 출력하고, 정의되어 있지 않으면 Hello, New World 를 출력하는 소스입니다. 이렇게 조건부컴파일을 할때 유용하게 사용되어 지는 것이 -D 옵션입니다.



.composition(구성)
:지금까지는 C++의 다중상속을 이용하여 부모에서 자식으로 혹은 자식에서 부모로 다중으로 상속받도록 하였습니다 이와는 다르게 클래스를 상속받지않고도 클래스 내부에 변수처럼 선언하여 사용하는 것이 가능합니다 이를 composition이라고 합니다

사용방법

class sonata :  public car
{
     private:
          audio myaudio; 


audio의 디폴트 생성자를 호출합니다

추가>>그렇다면 sonata에서 audio내부 속성(audio maker)을 호출하여 보겠습니다 어떻게 해야될까요?
간단합니다 아래의 코드(빨간색)를 추가합니다

class sonata :  public car
{
     private:
          audio myaudio; 
     public:

          sonata() : car(1234,,"HYUNDAI"),myaudio("JBL")
          
{

sonata() : car(1234,,"HYUNDAI"),myaudio("JBL")
의 경우 class가 오면 상속을 뜻하며 구성(오브젝트)가 오면 변수로 선언했음을 뜻합니다

참고>> 초기화 코드는 생성자에...

 class audio
{
    int k = 100;
 struct audio
{
    int k = 100

클래스에서 변수의 선언과 동시에 초기화가 되지 않습니다 위의 그림은 class를 struct로만
바꾸었습니다 즉 구조체에서는 초기화를 하지 않죠 클래스에서도 초기화를 하지 않습니다

초기화는 생성자에서 합니다



복습>>객체를 가리키는 포인터와 자동케스팅

A     AA;    객체
A    *AP;   포인터
B     BB;    객체
B    *BP;   포인터 라고 선언하였을때


그림의 왼편에 AP = &AA와 BP = &BB는 아무런 문제가 되지 않습니다 하지만 오른편의 그림을 보면 약간의 문제가 발생하게 됩니다 B가  A로 상속이 될때 B의 경우는 B A의 속성을 가지고 있기 때문에  AP를 넣어도 문제가 없습니다 이렇게 문제가 되지 않고 적용이 되는 것을 자동케스팅이라고 합니다 하지만 반대로 A의 경우에는 B의 속석을 가지고 있기 때문에 자동케스팅이 불가능합니다 

그렇다면 여기서 속성을 가지고 있는 상속된 객체는 자동케스팅이 가능하니 좋다!!라고 생각 할수 있습니다 하지만 이렇게 사용하기 위해서는 주의해야될점이 있습니다 

객체 배열의 경유 를 보겟습니다

B BB[10];
A *AP;
AP = BB;

AP = AP+1 (문제발생) 

A에 상속을 받는 B를 [10] 만큼이니칸 AB AB AB....10번이 생기는데 클래스 AB의 크기는 8byte크기를 차지하게됩니다 그런데 여기서 AP+1을 하게되면 4만큼을 가리키게 되는데 예를 들어 1004번지라고 한다면  아래 그림처럼 잘못된 위치를 참고하게 됩니다

 
.생성자와 소멸자를 클래스 밖에서 사용하기
: 생성자와 소멸자를 클래스 밖에 두어 사용이 가능합니다 사용방법은 스코프 연산자를 사용하면됩니다

사용하기전엔 간단한 문제를 풀어보겠습니다 문제는 아래 그림에서 B에서 k=100으로 값을 넣었을때 A에 k의 값 100을 받기 위해서는 어떻게 해야 될까요?


정답은 A::k = 100입니다 이 정답을 바탕으로 생성자와 소멸자를 클래스 밖에서 사용하도록 할려면 어떻게 해야할까요?

사용방법

class audio
{
     public:
          audio(); 
          audio(char *);
          ~audio();
};

audio::audio()
{

}
audio::~audio(0
{

}

Q>audio::audio()에 세미콜론을 붙힙니까?
함수의 정의는 세미콜론이 없고 변수의 정의는 세미콜론이 있습니다

.객체 배열 초기화
: main()에서 객체를 호출할때 호출 값을 배열에 저장하여 호출하는 방법은 아래와 같습니다
(다른코드(생성자 소멸자)들은 생략하였습니다)

초기화방법

class A
{
    int i;
    A();
    A(int)
    {
        this->i = i;
        cout <<this->i;
    }
    ~A();
}


int main()
{
    A aa[5] = {1,2,3,4,5};
    return 0;


그렇다면 인자가 2개인 객체의 배열은 초기화를 어떻게 할것인가?

A(int i,int j)  //인자가 2개

int
 main()
{
    A aa[5] = {A(1,1),A(2,2),A(3,3),A(4,4),A(5,5)};
    return 0;


결과보기>> 각각 잘 생성되며 소멸되는 것을 확인 할 수 있습니다


.for문 안에서의 객체생성
:for문에서 돌아가는 동안  생성 호출을 반복합니다 비효율적이고 최적화하기 어렵습니다 예를 들어보겠습니다 드라이버를 수리하기위해 사용해야 되는데 여러번 써야 될경우 한번만 가지러 갔다고 수리하는 동안에는 놓고 쓰는것이 편합니다 하지만 한번만 써야 될 경우에는 쓰고 제자리에 돌려 놓아야지 정리하기가 편합니다 이러한 경우도 마찬가지로 적용됩니다

for(int iCnt;iCnt<5;iCnt++)  //인자가 2개
{
    A temp(iCnt);



.전연과 main()의 실행순서 그리고 static
: main 함수가 먼저 실행된다는 생각을 가지게 됩니다 과연 main함수가 먼저 실행이 될까? 테츠트하여 보겠습니다

class A

A obj1(1);

void test()
{
    static A obj3(1000);
}

int main
{
    A obj2(2);


결과보기>> 어떤순서로 실해 될까요?

전역의 obj1 -> main의 obj2 -> test의 obj3순서로 생성되고 소멸은 순서가 반대로 되지 않았습니다
스테틱 먼저 소멸하고 전역이 소멸하는데 전역에서는 1000이 나중에 생성되어 소멸시에는 먼저 소멸된듯 합니다

참고>>static + 객체
:객체가 여러번 호출이 되어도 초기화는 한번만되고 그이상 호출하지 않습니다 하지만 한번은 호출되어야 합니다 이것으로 미루어 보아 c에서의 변수에 static사용되었을때와 같습니다



.new과 malloc
:C++에서 추가된 메모리할당 연산자로 new가 존재합니다. 참고로, malloc은 함수이지만, new는 연산자 입니다. 함수와 연산자로 비슷해 보이지만 다른점도 있습니다 

사용방법>> new에 띄우고 사이즈를 정해주면됩니다 메모리 해제는 delete 를 사용하면 됩니다

int main()
{
   int *old1;
   int *new1;

   old1 = (int*)malloc(sizeof(int));
   new1 = new int;

   free(old1);
   delete new1;
   return 0;



코드가 줄어들고 보기편하고 사용하기 쉽습니다

그럼, new/malloc에 대해 차이점을 정리해보겠습니다.
1. new는 연산자(operator), malloc은 함수
2. malloc() 함수은 c 에서 제공하는 함수이므로 c, c++ 에서 모두 사용 가능하지만,  new연산자는 c++에서만 사용가능합니다.
3. malloc()경우 반환형을 값을 알맞게 들어가도록 casting을 해야되지만 new의 경우에는 필요없습니다.
4. new는 클래스의 경우, 메모리를 할당하여 객체를 생성하면서, 객체의 디폴트 생성자를 자동으로 호출합니다. 
 
- 이점이 malloc() 함수와 가장 큰차이점중에 하나입니다. new연산자로 동적메모리를 할당받는 경우 자료형이 클래스나/구조체라면 자동으로 생성자가 호출된다는것입니다. 그러나, malloc은 객체만 생성합니다.

참고로, new로 할당된 동적메모리를 해제시 delete 연산자를 사용합니다. 이 delete를 사용하면, 소멸자가 호출되지만, free는 호출하지 않습니다.

정리하면, malloc을 좀더 편리하게 사용하도록 c++에서 제공하는 연산자가 바로 new 입니다.

주의: new/delete, malloc/free는 서로 한쌍을 이루어야 합니다. 만일, new을 사용하고, free로 메모리를 해제하거나, malloc으로 메모리를 할당받고 delete로 해제 하는것은 바람직하지 않습니다. c++언어 문법에도 이들의 혼용사용에 대해서 보장하는 내용이 존재 하지 않습니다.
 

참고>> 배열식 할당

   new1 = new int[3];
   delete[] new1;

 []를 delete만 사용하면 1개만 해제됩니다


참고>> java와 C++ 객체생성(?)

Java
int A; 지원을 위해 Integer(기본형에 관련된 자료형 존재)
Z obj; 4byte 

obj = new Z; (자바는 객체를 가리킬때 포인터로)
obj : 객체참조변수 

추가로 같은 이름으로
obj = new Z;
앞에 사용되었던것은 자동으로 free가 됩니다
 
C++
int A
Z* obj  20byte

C++ 동적할당을 받을것인가 선언할것인가 선택을 합니다 new를 하지않으면 동적할당을 받을수 없습니다
1)obj = new Z;
   delete Z;

2)obj = new Z;(이부분 잘모르겠음 댓글좀 달아주삼요)



추가>>객체를 생성할때 new를 이용하여 생성자 호출 할 수 있다고 하였는데 되는지 확인하여 보겠습니다 
그리고 malloc에서 클래스의 생성자와 소멸자를 호출하는지 확인해보겠습니다

A* old1;
A* new1;

old1 = (A*)malloc(sizeof(A));
free(old1);

new1 = new A;
delete new1;  


결과보기>>malloc로는 객체가 호출되지 않는것을 알수 있습니다 반대로 new를 사용하면 잘 됩니다!!


자 오늘의 수업내용은 여기까지 입니다~~~!!! 모두들 객체 잘 챙기셔서 수업시간에 기억상실증에 걸리지 맙시다!!!
728x90