기초 C++

작성자 : 김혜영

1. C++시작

1.1 C++이란?

C언어에서 기본적인 문법을 가져왔지만 C언어와는 다른 프로그래밍 언어. C’스타일’의 프로그래밍이 가능하다. 1979년에 최초로 출범하였다. 객체 지향 언어이지만 java, C#과 다르게 최소 단위가 함수 단위이다. (class없이 main함수만 있어도 동작가능하다.)

객체 지향(OOP; Object Orinted Programming)이란 컴퓨터 프로그래밍의 패러다임 중 하나이다. 프로그래밍에서 필요한 데이터를 상태와 행위를 가진 독립적인 객체로 만들고 객체간의 상호 작용을 통해 프로그래밍하는 방법이다. 대표적으로 java가 객체지향프로그래밍 언어이다.

1.2 C++언어의 특징

1 호환성

기존의 C언어의 문법적 체계를 그대로 계승해서 C 언어 프로그래밍과의 호환성(compatability)을 유지한다.

2 객체 지향 개념

소프트웨어의 재사용으로 생산성을 높이고 복잡하고 큰 규모의 소프트웨어 작성, 관리 유지 보수를 쉽게 하기 위해 객체 지향 개념을 도입했다.

3 엄격한 타입체크

어떤 변수를 사용하기 전에 변수의 데이터 타입을 선언하는 등의 동작을 취해야함. 실행 시간 오류의 가능성을 줄이고 디버깅을 돕는다.

4 실행 시간의 효율성 저하를 최소화

객체 지향 개념의 도입으로 멤버 함수의 호출이 잦아지고 이로 인해 실행 시간이 저하되는 비효율성을 막는다.

1.3 C언어에서 추가된 기능

1 함수 중복(Function Overloading)

매개 변수의 개수나 타입이 서로 다른 동일 이름의 함수를 선언할 수 있다.

int add(int a, int b, int c){
    return a + b + c;
}

int add(int a, int b){
    return a + b;
}

위의 코드처럼 작성해도 C++에선 오류가 발생하지 않는다. 매개 변수의 개수가 다르기 때문에 함수명이 같아도 다른 함수로 인식한다.

2 디폴트 매개 변수(default parameter)

매개 변수에 값이 전달되지 않는 경우 디폴트 값이 전달되도록 함수를 선언할 수 있다.

int minus(int x, int y = 1){
    return x - y;
}

int main(){
    cout<<minus(3)<<endl;
    cout<<minus(5,2)<<endl;
}

위와 같이 코드 작성 시 아래와 같은 결과를 확인할 수 있다.

2
3

처음 minus 함수를 사용했을 땐, y에 대한 매개 변수를 전하지 않았다. 이 때, 함수를 정의할 때 설정한 디폴트 매개변수의 값이 y로 전달되어서 2라는 결과를 출력한다. 만약, 두 가지 값 모두를 전달했다면 디폴트 매개변수는 무시되고 인자로 전달된 값으로 연산된다.

3 참조(reference)와 참조 변수

기존의 C문법엔 일반 변수와 포인터 변수라는 두 가지 변수가 존재한다. 간단하게 설명하자면, 일반 변수는 메모리 공간을 할당 받아 값을 직접 저장하는 변수이고 포인터 변수는 다른 변수의 주소 값을 저장하는 변수이다. C++ 문법에서 추가된 참조란 변수에 별명을 붙여 변수 공간을 같이 사용한다는 개념이다. 아래는 참조 변수를 선언하는 방법은 기존의 변수 선언 방식에서 자료형과 변수명 사이에 ‘&’ 기호를 추가하면 된다.

int main(){
    int num = 10;
    int& refer = num; 
    // refer은 참조 변수명. 
    // 이 코드는 num 변수의 주소를 refer에 저장한다는 의미이다.

    cout << "일반 변수 호출>> "<< num << endl;
    cout << "참조 변수 호출>> "<< refer << endl;
}

위와 같이 참조 변수를 선언하고 사용할 수 있다.

일반 변수 호출>> 10
참조 변수 호출>> 10

만약 변수의 주소를 출력하고 싶으면 아래와 코드를 추가하면 된다.

    cout << "일반 변수 주소>> "<< &num << endl;
    cout << "참조 변수 주소>> "<< &refer << endl;

참조에 대한 개념은 뒤에 더 자세하게 다룰 예정이다.

4 참조에 의한 호출(Call-by-Reference)

함수 호출시 참조를 전달할 수 있게 한다. 마찬가지로 뒤에서 자세하게 다룰 예정

5 new와 delete 연산자

동적 메모리 할당, 해제헤 사용되는 연산자이다.

6 제네릭 함수와 클래스(generics)

함수나 클래스를 데이터 타입에 의존하지 않고 일반화시킬 수 있게 한다.

1.4 C++의 객체 지향 특성

기술 면접을 볼 때, 면접관이 물어볼 수 있는 질문이니까 외워두면 좋다.

1 객체와 캡슐화

캡슐화는 데이터를 캡슐로 싸서 외부의 접근에서 데이터를 보호하는 객체 지향의 특성이다. C++에서는 클래스가 캡슐의 역할을 수행한다. 객체(object)는 클래스라는 틀에서 생겨난 실체이다. C++에선 이 실체를 인스턴스(instance)라고 지칭한다. C++의 클래스는 멤버 변수들과 멤버 함수들로 이루어지며, 접근지정자를 이용해 멤버들의 공개범위를 설정할 수 있다.

아래 코드는 Circle이라는 캡슐 틀을 만드는 코드이다.

class Circle{
    private:
        int radius;
    public:
        Circle(int r) { radius = r; }
        double getArea() { return 3.14*radius*radius; }
}; // class 선언이 끝나면 뒤에 세미콜론(;)을 꼭 붙여야한다. 

class내부에 적힌 public, private는 C++의 접근 지정자라고 지칭한다. private는 객체의 변수를 외부에 공개하지 않는다는 의미이고 public은 객체의 변수를 외부에 공개하겠다는 의미다. (protected라는 접근 지정자도 존재한다. 상속된 객체에 대해서만 변수를 공개한다.)

2 상속성

객체 지향 언어의 상속이란 자식이 부모의 유전자를 물려받는 것과 유사하다. C++에서 상속은 객체를 정의하는 클래스 사이에 상속 관계를 두어, 자식 클래스의 객체가 생성될 때 자식 클래스에 선언된 멤버뿐 아니라 부모 클래스에 선언된 멤버들도 함께 가지고 탄생한다.

class Phone{
    void call();
    void receive();
};

class MobilePhone : public Phone { // Phone의 기능을 상속받는다.
    void connectWireless();
    void rechange();
};

class MusicPhone : public MobilePhone{ // MobilePhone의 기능을 상속받는다. 
    void downloadMusic();
    void play();
};

위의 코드는 상속의 예시이다. MobilePhone 클래스는 Phone 클래스의 기능을 물려받는다. 마찬가지로 MusicPhone은 MobilePhone 클래스의 기능을 물려받는다.

3 다형성

다형성은 하나의 기능이 경우에 따라 서로 다르게 보이거나 다르게 동작하는 현상을 말한다. 예를 들면, + 연산자가 있다.

cout << 1+2 <<endl;
cout <<"hello "+"world"<<endl;

위에서 +는 두 가지 기능을 수행한다. 정수를 더하는 더하기 연산기능과 두 문자열을 붙이는 기능을 수행한다. 이렇게 하나의 연산자가 여러 기능을 수행하는 것을 다형성 중 하나인 연산자 중복(operator overloading)이라 지칭한다. 위에서 언급한 함수 중복(function overloading)도 다형성 중 하나이다.

C++ 다형성은 상속 관계에서도 나타난다. 부모 클래스의 어떤 기능이 존재하고 여러 개의 자식 클래스에서 서로 다르게 구현하는 경우를 함수 재정의 혹은 함수 오버라이딩(function overriding)이라고 부른다. 함수 오버로딩과 함수 오버라이딩은 다른 것이니 착오가 없어야한다.

1.5 C++ 프로그램 개발 과정

우리가 작성하는 C++ 프로그램 코드는 아쉽게도 컴퓨터는 이해하지 못한다. 컴퓨터가 우리의 코드를 이해하기 위해서는 일련의 과정이 필요하다.

프로그래밍 코드를 실행하는 과정은 프로그래밍 언어마다 방식이 모두 다르다. 다른 프로그래밍 언어는 직접 찾아보는 것을 추천!

아래 사진은 C++ 프로그래밍 과정을 플로우차트로 간단하게 표현한 사진이다. 하나씩 풀어가보자.

1

1 소스 파일(Source File)

C++ 소스프로그램은 표준 확장자가 cpp인 텍스트 파일이다. 텍스트 파일이기 때문에 소스 코드는 단순 텍스트 편집기를 이용하여도 프로그래밍은 가능하다. 하지만, 컴파일러 회사들이 지원하는 C++ 프로그램 개발의 모든 단계를 지원하는 통합 개발 환경을 이용하면 삶의 질이 올라가니 되도록 통합개발환경(Integrated Development Environment; IDE 예를 들면, MS사의 Visual Studio등이 있다.)을 사용하자. 아래는 hello.cpp의 내용이다.

std::cout <<"hello";

2 선행 처리기(Preprocessor)

선행 처리(Preprocess) 란 실행 파일을 생성하는 과정에서 컴파일하기 전, 소스 파일에 존재하는 선행 처리 지시문을 처리하는 작업을 의미한다. 대표적으로 라이브러리를 가져오는 코드인 #include 문이 있다. 선행 처리 지시문은 # 기호로 시작한다는 특징이 있다.

#include <iostream>
#define Max 500
#if
#ifdef
..

3 컴파일(complie)

컴파일이란 C++ 소스 프로그램이 문법에 맞게 작성되었는지 검사하고 목적파일(object file) 을 생성하는 과정을 뜻한다. 소스 파일은 자연어(고급언어)로 적혀진 텍스트 문장이어서 컴퓨터가 이해하지 못한다. 따라서 기계어 코드로 한 번 번역해주는 과정이 필요하다. 이 기계어 코드로 번역한 파일을 목적 파일이라고 하고 .obj 확장자를 가진다. 만약 컴파일러가 C++문법에 맞지 않게 작성된 코드를 발견하면 오류를 발생시킨다. 이 오류를 컴파일 에러라고 지칭한다. 앞서 작성한 hello.cpp 파일엔 문법적 오류가 없다고 가정하면 무사히 hello.obj 파일이 만들어진다.

4 링킹(linking)

컴파일 후 기계어로 구성된 목적 파일(object file)이 생성되었다 하더라도 목적 파일은 바로 실행될 수 없다. 소스 파일은 여러 라이브러리, 다른 C++ 프로그램에 있는 함수, 객체, 데이터를 사용하는 코드를 포함하고 있을 수 있다. 목적 파일에는 이들에 대한 참조 표시만 있을 뿐 코드를 포함하지 않는다. 즉, 목적파일은 온전한 실행파일이 아니다. 따라서 결합되어야만 비로소 실행 가능한 파일이 된다.

링킹이란 어떤 목적 파일이 참조하는 다른 목적 파일 속에 있는 함수, 객체, 데이터를 포함해 실행에 필요한 모든 기계어 코드를 확보해, 하나의 실행 파일로 만드는 과정이다. 링킹의 결과가 비로소 실행에 필요한 모든 요수를 포함한 하나의 실행 파일(exe 파일)이 만들어진다. 만약, 링킹 과정 중 목적 파일에서 참조하는 코드를 다른 목적 파일이나 C++ 표준 라이브러리 속에서 발견할 수 없으면 링크 오류가 발생한다. 실행 파일에는 실행에 필요한 모든 요소들이 들어 있다. hello.obj 파일을 링킹하면 hello.exe 파일이 만들어진다.

디버깅(Debugging)

실행 파일이 만들어지면 컴퓨터에서 바로 실행 가능하다. 하지만 논리적 프로그램에 논리적 오류가 있다면 실행 중 프로그램이 중단되거나 잘못된 결과를 내게 된다. 이렇게 프로그램의 오류 위치를 발견하거나 문제의 원인을 찾아 수정하는 과정을 디버깅(debugging) 이라고 지칭한다.

C++ 표준에서 C++ 소스 프로그램의 확장자는 .cpp이다. 하지만, 컴파일러에 따라서 .cxx, .c++, .cc, .C, .CC 등 다양한 확장자가 존재하므로 사용하는 컴파일러의 메뉴얼을 참조할 필요가 있다. 또한, 목적파일의 확장자도 운영체제마다 다르다. 윈도우 운영체제에선 .obj이지만 유닉스 운영체제는 .o를 사용한다. 실행파일은 윈도우 운영체제에선 .exe이지만 유닉스에선 정해진 확장자가 없다.

1.6 C++ 표준 라이브러리

개발자들은 자신이 필요한 함수나 클래스를 스스로 작성하기도 하지만 미리 만들어진 함수나 클래스를 활용하는 경우도 많다. C++ 표준 라이브러리 는 개발자들이 불러 쓸 수 있는 다양한 종류의 함수와 클래스가 컴파일된 목적 파일들이다.

1 C라이브러리

기존 C표준 라이브러리를 수용해 C++에서 사용할 수 있게하는 함수들. 라이브러리명이 c로 시작하는 특징이 있다. ex. cstring, cctype, cfloat…

2 C++ 입출력 라이브러리

콘솔 및 파일 입출력을 위한 함수와 클래스, 제네릭 프로그래밍을 지원하기 위해서 템플릿으로 작성함 ex. fstream, iostream, ostream….

3 C++ STL 라이브러리

제네릭 프로그래밍을 지원하기 위해 템플릿으로 작성된 유용한 함수와 클래스를 포함하는 라이브러리 ex. algorithm, list….

C++프로그래밍이란 무엇인지에 대해서 알아봤다. C++은 임베디드 시스템, 딥러닝 등에서 많이 사용되니 한 번쯤 공부해보는 것도 좋다.

Categories:

etc