(0829) C++ 학습일지(1)

런치·2023년 8월 29일
0

C++

목록 보기
1/14
post-thumbnail
  1. from C to C++
  1. 확장자의 변경 from (.c) to (.cpp)

    // Ubuntu OS 
    cp (디렉토리 지정)/ main.c main.cpp
    cp (디렉토리 지정)/stack.h stack.h
    cp (디렉토리 지정)/stack.c stack.cpp
    // How to Compile in UbuntuOs
    g++ -c stack.cpp
    g++ -c main.cpp
    g++ -c stack.h
    g++ -o testStack main.o stack.o

    gedit으로 편집 : gedit main.cpp stack.h stack.cpp

  1. push(&s1,100) -> s1.push(100)
  1. 멤버함수는 반드시 객체를 통해서 호출한다
    예시) s1.pop(), s2.pop()
  2. 모든 멤버함수는 자신과 호출된 객체를 가리키는 this 포인터를 갖는다.
  3. 데이터와 관련된 연산은 같은 멤버로 구성, 캡슐화(encapsulation)
//수정 전 코드
#include <stdio.h>
#include "stack.h"

int main(void)
{
	Stack s1, s2;
	initStack(&s1, 10);
	initStack(&s2, 100);

	push(&s1, 100);
	push(&s1, 200);
	push(&s1, 300);
	
	printf("s1 1st pop() : %d\n", pop(&s1));
	printf("s1 2nd pop() : %d\n", pop(&s1));
	printf("s1 3rd pop() : %d\n", pop(&s1));


	push(&s2, 900);
	push(&s2, 800);
	push(&s2, 700);
	
	printf("s2 1st pop() : %d\n", pop(&s2));
	printf("s2 2nd pop() : %d\n", pop(&s2));
	printf("s2 3rd pop() : %d\n", pop(&s2));

	cleanupStack(&s1);
	cleanupStack(&s2);
	return 0;
}
int main() {
    Stack s1(10);
    Stack s2(100);

    s1.push(100);
    s1.push(200);
    s1.push(300);

    printf("s1 1st pop() : %d\n", pop(&s1));
	printf("s1 2nd pop() : %d\n", pop(&s1));
	printf("s1 3rd pop() : %d\n", pop(&s1));

    s2.push(900);
    s2.push(800);
    s2.push(700);
    
    printf("s2 1st pop() : %d\n", pop(&s2));
	printf("s2 2nd pop() : %d\n", pop(&s2));
	printf("s2 3rd pop() : %d\n", pop(&s2));
  1. malloc() / free() 함수 --> new / delete 연산자

malloc() / free() 와 new / delete 에 대한 비교

  1. 메모리 할당:

    • C (malloc): malloc() 함수는 동적으로 메모리를 할당하기 위해 사용
      ex) int* ptr = (int*)malloc(sizeof(int));
      malloc()은 할당한 메모리의 크기만큼의 바이트를 할당, 초기화 X

    • C++ (new): new 는 C++에서 동적으로 메모리를 할당하기 위해 사용
      ex) int* ptr = new int;
      new는 할당한 메모리를 초기화하며, 객체의 경우 생성자도 호출

  2. 메모리 해제:

    • C (free): free()malloc()으로 할당된 메모리를 해제하는 데 사용
      ex)free(ptr);
      free()를 호출하면 해당 메모리 블록 해제, 포인터 유효하지 않음
    • C++ (delete): deletenew로 할당된 메모리를 해제하는 데 사용
      ex)delete ptr;
      delete를 호출하면 해당 객체의 소멸자가 호출, 할당된 메모리 블록이 해제,포인터는 더 이상 유효하지 않음
  3. 배열 할당 및 해제:

    • C (malloc + free): C에서 배열을 할당하려면 malloc()을 사용해야 하며, 해제할 때는 free()를 사용
    • C++ (new[] + delete[]): C++에서 배열을 할당하려면 new[] 를 사용하고, 해제할 때는 delete[] 를 사용
      new[]로 할당된 배열은 해당 크기 정보와 함께 메모리에 저장 delete[]를 호출하면 배열의 각 요소에 대해 소멸자가 호출되며 할당된 메모리 블록이 해제
  4. 예외 처리:

    • C (malloc + free): malloc()free()는 예외 처리를 지원하지 않아 메모리 할당 또는 해제 과정에서 문제가 발생하면 프로그램이 비정상적으로 종료될 수 있다.
    • C++ (new + delete): newdelete는 C++에서 예외 처리를 지원함
      할당 또는 해제 중에 문제가 발생하면 예외가 throw되어 적절한 예외 처리 메커니즘을 통해 처리가능
//수정 전 코드 <stack.cpp>
#include <stdlib.h>
#include <assert.h>
#include "stack.h"

void initStack(Stack *ps, int size)
{
	ps->pArr = malloc(sizeof(int) * size);
	assert(ps->pArr /* != NULL */);
	
	ps->size = size;
	ps->tos = 0;
}

void cleanupStack(Stack *ps)
{
	free(ps->pArr);
}


void push(Stack *ps, int data)
{
	assert(ps->tos != ps->size);
	
	ps->pArr[ps->tos] = data;
	++ps->tos;
}

int pop(Stack *ps)
{
	assert(ps->tos /* != 0 */);

	--ps->tos;
	return ps->pArr[ps->tos];
}
//수정 후 코드
#include <cassert> // <cassert> 로 변경
#include "stack.h"

class Stack {
private:
    int* pArr;
    int size;
    int tos;

public:
    Stack(int s) : size(s), tos(0) {
        pArr = new int[size]; // malloc() 에서 new[]로 변경
    }

    ~Stack() {
        delete[] pArr; // free()에서 delete[]로 변경
    }

    void push(int data) {
        assert(tos != size);
        pArr[tos] = data;
        ++tos;
    }

    int pop() {
        assert(tos != 0);
        --tos;
        return pArr[tos];
    }
};
  1. 구조체 멤버에 접근지정자 ( private / public ) 를 사용
  1. 내부구현(implemetation)은 숨기고, 인터페이스는(interface)는 보인다.
  1. 허용된 연산을 통해서 내부 구현에 접근할 수 있다.
  • 정보 은닉(information/data hiding) == 캡슐화(encapsulation)
//수정 후 코드
#include <cassert> // <cassert> 로 변경
#include "stack.h"

class Stack {
private: //private로 지정 클래스 내부에서만 사용 가능
    int* pArr;
    int size;
    int tos;

public: // public 으로 지정 클래스 외부에서도 사용 가능
  	Stack(int s) : size(s), tos(0) {
          pArr = new int[size]; 
      }

    ~Stack() {
          delete[] pArr; 
      }

    void push(int data) {
          assert(tos != size);
          pArr[tos] = data;
          ++tos;
      }
  1. 생성자(Constructor) / 소멸자(Destructor)
  1. 생성자 : 객체가 생성될 때, 자동적으로 호출되는 멤버함수
  1. 소멸자 : 객체가 소멸될 때, 자동적으로 호출되는 멤버함수
// 수정 후 코드
public: 
//생성자로써 initStack(Stack *ps,int size)에서 Stack(int s)으로 변경
  	Stack(int s) : size(s), tos(0) { 
          pArr = new int[size]; 
      }
//소멸자로써 void cleanupStack(Stack *ps) 에서 Stack()으로 변경
    ~Stack() {
          delete[] pArr; 
      }
  1. struct --> class

class(C++) = struct(C) + 멤버함수 + 접근지정자

C의 struct와 C++의 class는 모두 데이터와 함수를 하나의 유닛으로 그룹화하는데 사용되지만, C++의 class는 더 많은 기능과 특성을 제공하여 객체 지향 프로그래밍의 원칙을 더 쉽게 적용할 수 있도록 한다.

  1. 캡슐화 (Encapsulation):

    • C의 struct: C의 struct는 멤버 변수만을 가지며, 함수를 정의할 수 없다. 데이터의 그룹화는 가능하지만, 해당 데이터를 다루는 함수를 함께 묶을 수 없음

    • C++의 class: C++의 class는 멤버 변수와 멤버 함수를 함께 포함하여 객체의 상태와 동작을 하나로 묶을 수 있다. 이를 통해 데이터와 데이터를 다루는 동작을 함께 캡슐화하여 더 모듈화된 코드를 작성할 수 있다.

  2. 접근 제어 (Access Control):

    • C의 struct: C의 struct는 기본적으로 모든 멤버가 public으로 설정되어 외부에서 멤버 변수에 직접 접근이 가능하며, 캡슐화의 개념이 부족

    • C++의 class: C++의 class는 기본적으로 모든 멤버가 private으로 설정, 이를 통해 외부에서 직접적으로 접근하는 것을 제한하고, public, private, protected 등의 접근 제어 지시자를 사용하여 적절한 접근을 조절

  3. 생성자와 소멸자 (Constructor and Destructor):

    • C의 struct: C의 struct는 생성자와 소멸자를 가질 수 없다. 초기화 작업과 정리 작업을 구현할 수 없다.

    • C++의 class: C++의 class는 생성자와 소멸자를 가질 수 있다. 객체의 초기화와 정리 작업을 효과적으로 관리할 수 있습니다.

  4. 상속 (Inheritance)과 다형성 (Polymorphism):

    • C의 struct: C의 struct는 상속과 다형성을 지원하지 않는다.

    • C++의 class: C++의 class는 상속과 다형성을 지원하여 객체 지향 프로그래밍의 핵심적인 개념을 적용할 수 있다.

  5. 멤버 함수 및 멤버 변수의 초기화:

    • C의 struct: C의 struct는 멤버 변수를 초기화하지 않아 사용자가 수동으로 초기화해야 함

    • C++의 class: C++의 class는 생성자를 통해 멤버 변수를 초기화할 수 있다. 이를 통해 객체 생성 시 초기값을 제공하거나, 초기화 로직을 더 효과적으로 관리할 수 있다.

간단하게 말해, C++의 class는 C의 struct보다 객체 지향 프로그래밍을 더 쉽게 적용하도록 해주는 다양한 특성과 기능을 제공, C++의 class를 사용하면 코드의 모듈화, 캡슐화, 상속, 다형성 등을 더 효과적으로 활용할 수 있다.

  1. printf() --> cout << ??
  1. std::cout (C++)은 <iostream>헤더에 속하며, 스트림의 유형의 객체이다.
    출력하려는 값의 자료형을 컴파일러가 검사할 수 있다.
std::cout << 2 << endl; //int형 출력 함수 호출
std::cout <<"2"<< endl; //string형 출력 함수 호출
  • 파일 입출력(fstream) 스트링 입출력(stringstream)에서도 표준 입출력과 동일한 인터페이스를 사용하므로 편리함, printf()에 비해 속도가 느림
  • endl사용
  1. printf()<cstdio>헤더에 속하며, 형식화된 문자열을 표시하는데 주로 사용
    cout과 달리 출력하려는 값의 자료형을 컴파일 할 수 없기 때문에,
    버그가 일어날 수 있지만, cout에 비해 처리 속도가 빠르다.
  • \n사용
profile
점심을 안먹음

0개의 댓글