Cplusplus 복습

ChoRong0824·2023년 4월 14일
0

C

목록 보기
12/17
post-thumbnail

Cplusplus 를 처음부터 복습 하면서, 이땐 그냥 그렇구나 라고 넘겼지만, 지금은 "왜?" 라는 생각이 드는 것들이 있을 수도 있고, 시험 전에 기본 개념에 대해서, 기본적이면서 필수적인 부분을 한번 더 상기시키기 위해 포스팅 하였습니다.
글 형식이 자유로워 읽기엔 다소 불편할 수 있습니다,,,
제가 공부할 때, 필요한 부분만 포스팅 되었으며,
제가 이해한 내용을 바탕으로 작성되었습니다, 혹여 다르게 해석되거나 틀린 부분이 있다면 댓글로 피드백 부탁드리겠습니다.

// 함수 호출
n = adder(24567,98374);

int adder(int a,int b){
	int sum;
    	sum = a+b;
        return sum;
}

포인터, 포인터란 주소를 가리킴.
*를 사용해서 주소를 가리킴.

예,
int b =10;
int* a= &b; // b가 저장된 메모리의 주소를 가리킴.

쉽게 설명하자면 int b 로 초기화하면 b 라는 변수에는 숫자 10이 저장됩니다.
즉, 변수에 저장된다는 것입니다. 근데 이 변수는 정수형으로 지정해줬으며, 메모리에 저장이 되어야합니다. 그래야 사용할 수 있으니까요.
즉, 변수는 n 이지만 주소값은 랜덤으로 아무 값이나 할당 받습니다.
이것은 찍어보면 알 수 있습니다. (&)
따라서, 변수 b 를 가리키는 것이 아니라, 변수 b가 저장되어있는 메모리의 주소를 가리킨다고 보면 됩니다.
참고로, 변수 b 에는 여러 값이 할당 될 수 있습니다. (이게 포인트)
만약 int 형이라면 4 Byte를 저장할 수 있는 것입니다. 4Byte는 32 bit가 됩니다.
8bit는 1byte이기 때문이죠.
그러니까 int형으로 지정한 변수 n을 초기화 했다면, 4바이트의 메모리를 할당 받는 것입니다.
따라서, 이 메모리에 접근하려면 포인터를 사용하거나 변수를 사용하면 되는 것입니다.
(참고로 변수를 사용하면 메모리 직접접근이 아님)


캡슐화

데이터를 캡슐로 싸서 외부의 접근으로부터 보호함. (데이터 은닉)
클래스 (class키워드)로 캡슐 표현.
보통 많은 책들이 예시로 붕어빵을 예시로 듭니다,
찍어내는 붕어빵 틀을 클래스(객체를 정의하는 틀),
객체 생성하여(붕어빵 생산), 다양한 색상의 붕어빵 (실체_객체들)

클래스

클래스 - 객체를 만드는 틀
객체 - 클래스라는 틀에서 생겨난 실체
객체 -실체

  • 멤버 (클래스 안에 있는 부분들)
class Circle{
	private:
    int radius;
    public:
	Cricle(int r){
    radius = r;
    }
    double getArea(){
    return 3.14*radius*radius;
    }
};

아, 맞다! 참고로, void는 리턴 값이 없다는거 알고 계시죠? ㅎㅎ 모른다면 이제 아시면 됩니다 !,,
참고로 c++은 c랑 다르게 void main() 을 하지 않고, int main()을 해야합니다 !

상속

자식이 부모의 유전자를 물려 받는 것과 유사.
자바로 따지면 extends로 상속할 수 있습니다.
하지만, c++은

class Phone{
	void call();
    void receive();
};
class MobilePhone : public Phone{ // Phone을 상속받습니다.
	void connectWireless();
    void recharge();
};
class MusicPhone : public MobilePhone{ // MobilePhone을 상속받음
	void downloadMusic();
    void play();
};

다형성

하나의 기능이 경우에 따라 다르게 보이거나 다르게 작동하는 현상.
연산자 중복, 함수 중복, 함수 재정의(overriding)

오버라이딩 / 오버로딩 차이점을 모르신다면,
꼭 집고 넘어가세요 !

  • 오버로딩
    이름이 같은 메소드로 매개변수, 상황에 따라 효율적으로 활용함.
  • 오버라이딩
    덮어쓰기, 재정의

c++에 객체지향을 도입한 목적

이전에는 수학 계산이나 통계 처리에 편리한 절차지향 언어가 적합했습니다.
그러나,
현대의 SW는 물체 혹은 객체의 상호 작용에 대한 묘사가 필요,
실세계는 객체로 구성된 세계입니다. (모든 것이 객체라고 보면됨).
객체를 중심으로 하는 OOP가 적합함에 따라 도입되었습니다.

제네릭 함수와 제네릭 클래스

  • 제네릭 함수
    동일한 프로그램 코드에 다양한 데이터 타입을 적용할 수 있게 일반화 시킨 함수
  • 제네릭 클래스
    동일한 프로그램 코드에 다양한 데이터 타입을 적용할 수 있게 일반화 시킨 클래스
  • template 키워드로 선언
    템플릿 함수 || 템플릿 클래스라고도 부름

#은 전처리자 라고하며 해당 언어에게 내리는 지시를 의미합니다.
#include <iostream> 전처리기 c++에게 내리는 지시. 헤더파일을 컴파일 전에 소스에 확장하도록 지시합니다.
using namespace std; c++에서 정의한 이름공간 중 하나

cin 특징

  • 입력에 버퍼를 내장하고 있음
  • Enter 키가 입력될 때까지 입력된 키를 입력 버퍼에 저장함.
    도중에 Backspace 키를 입력하면 입력된 키 삭제함.

c++ 문자열

표현 방식 : 2가지

  1. c- 스트링 방식 : \0로 끝나는 문자 배열
    예)
char name [6] = {'G','r','a','c','e','\0'};
또는
char name2[10] = "Grace";
// 이렇게 되면 


로 저장됨.

  1. string 클래스 이용
  • <string> 헤더 파일에 선언됨.

c언어에서 사용한 함수 사용 가능.
strcmp(), strlen(), strcpy() 등 을 사용하려며느 c++ 에선,
<cstring> 헤더 파일을 사용하는 것이 바람직하며,
이게 c++ 표준 방식입니다. 필자도 이를 권장합니다.
-> string 클래스는 string 헤더파일 써야함. (오해 노노!)

char name[6]; // 5개의 문자를 저장할 수 있는 char 배열입니다.
왜냐하면, 마지막에 \0 이 포함되어 있기 때문입니다.
char name[11]; // 한글은 5개 글자, 영어는 10개 까지 저장할 수 있습니다.


공백이 낀 문자열 입력 받는 방법

cin.getline()으로 공백이 낀 문자열 입력을 받을 수 있습니다.

  • 형식 : cin.getline(char buf[], int size, char delimitChar)
    buf에 최대 size-1 개의 문자 입력. 끝에 \0 붙임
    delimitChar를 만나면 입력중단. 끝에 \0 붙임
    - delimitChar 의 디폴트 값은 \0 (Enter 키)
char address[100];
cin.getline(address, 100, '\n');  // 최대 99개의 문자를 읽어,
// address 배열에 저장함. 도중에 ENTER 키를 만나면 입력 중단됨.

C++에서 문자열 다루는 string 클래스

  • c++ 표준 클래스이며, c++에서 강력 추천합니다.
  • 문자열 크기에 따른 제약이 없습니다.
    - string 클래스가 스스로 문자열 크기에 맞게 내부 버퍼를 조절합니다. (키포인트)
  • 문자열 복사, 비교, 수정 등을 위한 다양한 함수와 연산자 제공합니다.
  • 객체 지향적입ㄴ디ㅏ.
  • string 헤더 파일에 선언 해야 사용할 수 있습니다.

getline()은 string 타입의 문자열을 입력 받기 위해 제공되는 전역 함수입니다.

string 클래스를 이용한 문자열 입력 다루기

아래 예시를 통해 익혀보시면 될 것 같습니다.
이때, 중요한 것은 getline() 사용법과,+ 로 문자열 연결 가능하며, 빈칸을 포함하는 문자열이 입력 가능하다. 라는 점입니다.

#include <iostream>
#include <string> 
using namespace std;

int main() {
	string song("Falling in love with you"); // 문자열 song
	string elvis("Elvis Presley"); // 문자열 elvis
	string singer; // 문자열 singer

	cout << song + "를 부른 가수는"; // + 로 문자열 연결
	cout << "(힌트 : 첫글자는 " << elvis[0] << ")?";  // [] 연산자 사용

	getline(cin, singer); // 문자열 입력
	if(singer == elvis)  // 문자열 비교
			cout << "맞았습니다.";
	else
			cout << "틀렸습니다. "+ elvis + "입니다." << endl; // +로 문자열 연결
}
![](https://velog.velcdn.com/images/ohoh7391/post/791008de-32aa-492a-abb7-230d3ad2bcaa/image.png)

참고 !,


c++ 객체는 멤버함수와 멤버변수로 구성됩니다.
이때, 멤버변수 = 객체의 상태, 멤버함수 = 객체의 행동 으로 구성됩니다.

멤버 변수

bool on = true;
int channel = 8;
int volume = 16;

멤버 함수

void powerOn()
void powerOff()
void increaseChannel()
void decreaseChannel()

객체 생성 및 활용 설명

  • 객체 이름 및 객체 생성
    Circle donut; // 이름이 donut인 Circle 타입의 객체 생성
    Circle = 객체의 타입. 클래스 이름, donut = 객체 이름
  • donut.radius = 1; // donut 객체의 radius 멤버 값을 1로 설정
    donut는 객체이름, radius는 멤버변수, 그 사이 중간에
    . 은, 객체 이름과 멤버 사이에 . 연산자 이며 값 설정
  • double area = donut.getArea(); //donut 객체의 면적 알아내기
    donut는 객체이름, . 객체 이름과 멤버사이 연산자, getArea()는 멤버함수 호출

이젠 실전입니다.
파이팅 !

3-2 정답,


생성자

  • 객체가 생성되는 시점에서 자동으로 호출되는 멤버 함수
  • 클래스 이름과 동일한 멤버 함수
class Circle {
		// 2개의 생성자 중복 선언	
		Circle(); // 클래스 이름과 동일
		Circle(int r); // 리턴 타입 명기하지 않음.
};

//  생성자 함수 구현

// 매개 변수 없는 생성자
Circle::Circle() {
}

// 매개 변수를 가진 생성자
Circle::Circle(int r) {
}

생성자의 목적

  • 객체가 생성될 때, 객체가 필요한 초기화를 위해
    - 멤버 변수 값 초기화, 메모리 할당, 파일 열기, 네트워크 연결 등

생성자 이름

  • 반드시 클래스 이름과 동일

생성자는 리턴 타입을 선언하지 않는다.

  • 리턴 타입 없음. void 타입도 안됨

객체 생성 시 오직 한 번만 호출

  • 자동으로 호출됨. 임의로 호출할 수 없음. 각 객체마다 생성자 실행

생성자는 중복 가능

  • 생성자는 한 클래스 내에 여러 개 가능
  • 중복된 생성자 중 하나만 실행

생성자가 선언되어 있지 않으면 기본 생성자 자동으로 생성

  • 기본 생성자 – 매개 변수 없는 생성자
  • 컴파일러에 의해 자동 생성

객체 생성 및 생성자 실행 과정

생성자가 다른 생성자 호출(위임 생성자)

여러 생성자에 중복 작성된 코드의 간소화를 위해 사용됨.

  • 타겟 생성자와 이를 호출하는 위임 생성자로 나누어 작성해야합니다.
    - 타겟 생성자 : 객체의 초기화를 전담하는 생성자
    - 위임 생성자 : 타겟 생성자를 호출하는 생성자, 객체 초기화를 타겟 생성자에 위임합니다.

생성자에서 다른 생성자 호출 연습 (위임 생성자 만들기)

main.cpp

#include "Circle.h"

int main(){

    Circle donut; // 매개 변수 없는 생성자 호출
    double area = donut.getArea(); // 위임 생성자 호출함.

    cout<< "donut 면적은" <<area <<endl;

    Circle pizza(30); // 매개변수 있는 생성자 호출 거기에 30 대입함.
    area = pizza.getArea();
    cout <<"pizza 면적" <<area <<endl;

    return 0; // 이부분은 제거해도 잘 작동함.
}

Circle.hpp

#ifndef CIRCLE
#include <iostream>

using namespace std;

class Circle
{
private:
    /* data */
public:
    int radius;
    // 위임 생성자
    Circle();
    Circle(int r);  // 타겟 생성자
    double getArea();
    ~Circle();
};

// 위임 생성자
Circle::Circle():Circle(1){ 
}
Circle::Circle(int r){
    radius =r;
    cout << "Radius" << radius << "Circle CREATE"<<endl;
}
double Cirlce::getArea(){
    return 3.14*radius*radius;
}

Circle::~Circle()
{
}


#endif // CIRCLE

위에 있는 이미지 로직이랑 비교하면서 확인하면됨.

다양한 생성자의 멤버 변수 초기화 방법

멤버변수의 초기화와 위임 생성자 활용

다음 포인터 클래스의 멤버 x,y를 , 생성자 서두에 초기값으로 초기화하고,
위임 생성자를 이용하여 재작성

class Point{
	int x,y;
public:
    Point();
    Point(int a,int b)
};
    Point::Point(){
    x=0; y=0;
    }
    Point::Point(int a, int b){
    x=a; y=b;
    }

재작성 코드


기본 생성자

  1. 생성자는 꼭 필요할까요?
    네, 필요합니다. c++ 컴파일러는 객체가 생성될 때, 생성자를 반드시 호출합니다.
  2. 개발자가 클래스에 생성자를 작성해 놓지 않았다면 ?
    컴파일러에 의해 기본 생성자가 자동으로 생성됩니다.
  • 클래스에 생성자가 하나도 선언되어 있지 않은 경우, 컴파일러가 대신 삽입해주는 생성자 입니다.
  • 매개변수 없는 생성자이며, 디폴트 생성자라고도 불립니다.
class Circle{
...
	Circle(); // 기본 생성자
};

예제 3-6.

#include "Rectangle.h"

int main(){

    Rectangle rect1; 
    Rectangle rect2(3,5);
    Rectangle rect3(3);

    if (rect1.isSquare()){
        cout << "rect1은 정사각형입니다." << endl;
    }
    if (rect2.isSquare()){
        cout << "rect1은 정사각형입니다." << endl;
    }
    if (rect3.isSquare()){
        cout << "rect1은 정사각형입니다." << endl;
    }
    

    return 0;
}

이것을 보고 class를 만드시오.
(참고, 객체를 3개 초기화(=생성) 하니까, 생성자 3개 필요함.)
정답,

#ifndef RECTANGLE
#include <iostream>

using namespace std;

class Rectangle
{
private:
    int width, height;
public:
    Rectangle();
    Rectangle(int w,int h);
    Rectangle(int length);
    bool isSquare();
    ~Rectangle();
};

Rectangle::Rectangle(){
    width = height =1;
}
Rectangle::Rectangle(int w, int h){
    width =w;
    height=h;
}
Rectangle::Rectangle(int length){
    width = height = length;
}
boo Rectangle::isSquare(){
    if (width==height) return true;
    else return false;
}

Rectangle::~Rectangle()
{
}




#endif //RECTANGLE

소멸자

  • 객체가 소멸되는 시점에서 자동으로 호출되는 함수

  • 오직 한 번만 자동 호출, 임의로 호출할 수 없음.

  • 객체 메모리 소멸 직전 호출됨.

  • 즉, 소멸자는 객체가 사라질 때, 마무리 작업을 위한 것입니다.
    소멸자는 매개 변수 없는 함수이며, 소멸자는 한 클래스 내에 오직 한 개만 작성가능합니다.


소멸자는 참고로 객체 생성의 반대순으로 소멸됩니다.

생성자/소멸자 실행 순서

객체가 선언된 위치에 따른 분류

  • 지역 객체
    함수 내에 선언된 객체로서, 함수가 종료하면 소멸됩니다.
  • 전역 객체
    함수의 바깥에 선언된 객체로서 프로그램이 종료할 때 소멸됩니다.

객체 생성 순서

  • 전역 객체는 프로그램에 선언된 순서로 생성
  • 지역 객체는 함수가 호출되는 순간에 순서대로 생성합니다.

객체 소멸 순서

  • 함수가 종료하면, 지역 객체가 생성된 순서의 역순으로 소멸
  • 프로그램이 종료하면, 전역 객체가 생성된 순서의 역순으로 소멸합니다.


접근 지정자 (데이터 은닉 필요)

예제 3-9

Cplusplus 구조체

C 와 동일하지만,

  • 구조체의 디폴트 접근 지정 - public,
  • 클래스의 디폴트 접근 지정 - private 입니다.

C++이 헤더파일과 분할시, 돌아가는 로직

헤더파일에 꼭 들어가야하는 부분

#ifndef CIRCLE
#define CIRCLE

#endif

이렇게 해줘야 헤더 파일의 중복 include 문제를 조건 컴파일로 해결할 수 있습니다.

마지막으로, 가독성을 위해 객체 포인터 부분은 따로 포스팅 하겠습니다.

profile
컴퓨터공학과에 재학중이며, 백엔드를 지향하고 있습니다. 많이 부족하지만 열심히 노력해서 실력을 갈고 닦겠습니다. 부족하고 틀린 부분이 있을 수도 있지만 이쁘게 봐주시면 감사하겠습니다. 틀린 부분은 댓글 남겨주시면 제가 따로 학습 및 자료를 찾아봐서 제 것으로 만들도록 하겠습니다. 귀중한 시간 방문해주셔서 감사합니다.

0개의 댓글