Hello C++ 입출력

출력(cout)

#include <iostream>
// io : input, output
// 입출력을 흘러가게 하는 역할을 하는 라이브러리

int main()
{
    std::cout << "Hello C++" << std::endl;
    // std::cout 객체 : c++에서 화면에 출력시 사용하는 출력 객체
    // std라는 이름 공간에 존재하는 cout 객체를 사용하겠다는 의미
    return 0;
}
Hello C++

:: : 스코프 연산자, 영역 결정 연산자

#include <iostream>

int main()
{
    int a = 10;
    float b = 3.14f;
    char c = 'A';

    std::cout << a << std::endl;
    std::cout << b << std::endl;
    std::cout << c << std::endl;
    return 0;
}
10
3.14
A
#include <iostream>

using namespace std;
int main()
{
    int a = 10;
    float b = 3.14f;
    char c = 'A';

    cout << a << endl;
    cout << b << endl;
    cout << c << endl;

    return 0;
}

using namespace std;를 통해 간단하게 작성할 수 있다.

이름 공간(namespace)

특정 공간에 이름을 지정해 준다는 의미이다.

#include <iostream>

namespace A
{
    void func(void)
    {
        std::cout << "A학급 주성" << std::endl;
    }
}

namespace B
{
    void func(void)
    {
        std::cout << "B학급 주성" << std::endl;
    }
}

int main()
{
    A::func();
    return 0;
}
A학급 주성

입력(cin)

#include <iostream>

using namespace std;
int main()
{
    int a;
    float b;
    char c;

    cin >> a;
    cout << "정수값 출력 : " << a << endl;
    cin >> b;
    cout << "정수값 출력 : " << b << endl;
    cin >> c;
    cout << "문자열 출력 : " << c << endl;

    return 0;
}
1
정수값 출력 : 1
1.4
정수값 출력 : 1.4
a
문자열 출력 : a

C++에서의 새로운 규칙

변수 선언

C에서는 변수들을 먼저 선언해주고 코드를 작성해야 했지만, C++에서는 중간에서도 변수를 선언할 수 있다.

매개변수 기본값 설정

  • 선언부
void func(int a = 10, int b = 20);
  • 호출부1
func(100, 200); // 전달인자의 값은 각각 100과 200
  • 호출부2
func(50); // 전달인자의 값은 50, 20
func(); // 전달인자의 값은 10, 20

매개변수 기본값을 설정할 경우, 호출부에서 매개변수를 생략하더라도 기본값이 설정되게 된다.

#include <iostream>
using namespace std;

void func(int a = 10, int b = 20);

int main()
{
    func(); // 전달인자x
    func(100);
    func(100, 200);
    return 0;
}

void func(int a, int b)
{
    cout << "두 전달인자 출력: " << a << " " << b << endl;
}
두 전달인자 출력: 10 20
두 전달인자 출력: 100 20
두 전달인자 출력: 100 200

전역변수와 지역변수

C언어에서는 전역변수와 지역변수의 이름이 같을 시 지역변수가 전역변수보다 우선권을 가진다.

#include <stdio.h>

int nTemp = 10;
int main()

{
    {
        int nTemp = 20;
        printf("nTemp의 값은 : %d이다.\n", nTemp);
    }
    printf("nTemp의 값은 : %d이다.\n", nTemp);
}
nTemp의 값은 : 20이다.
nTemp의 값은 : 10이다.

C++ 언어에서는 전역변수와 지역변수 존재시 영역 결정 연산자::을 통해 지역 내에서 전역변수를 출력할 수 있다.

#include <iostream>
using namespace std;
int nTemp = 10;

int main()
{
    {
        int nTemp = 20;
        cout << "nTemp = " << nTemp << endl; 
        cout << "::nTemp = " << ::nTemp << endl; 
    }
    cout << "nTemp = " << nTemp << endl; 
}
nTemp = 20
::nTemp = 10
nTemp = 10

인라인 함수

코드 라인 자체가 호출부 안에 포함된다는 의미, #define 매크로의 단점을 보완하고, 일반 함수 호출의 부하를 덜어준다. 최근에는 컴파일러 성능이 좋아 인라인 함수를 붙여주지 않아도 컴파일러가 필요한 기능에 인라인 함수로 동작하게 만들어준다.

오버로딩

C에서의 두 숫자의 합을 반환하는 함수의 경우, 입력값이 정수, 실수, 문자값을 매개변수로 사용하는 함수 모두 따로 선언해줘야 했다.

#include <stdio.h>

int AddI(int a, int b);
double AddD(double a, double b);
char AddC(char a, char b);

int main()
{
    int i;
    double d;
    char c;

    i = AddI(10, 20);
    d = AddD(3.14, 1.59);
    c = AddC('A', 1);    
    printf("정수값 출력 : %d\n", i);
    printf("실수값 출력 : %f\n", d);
    printf("문자값 출력 : %c\n", c);
}

int AddI(int a, int b)
{
    return a + b;
}
double AddD(double a, double b)
{
    return a + b;
}
char AddC(char a, char b)
{
    return a + b;
}
정수값 출력 : 30
실수값 출력 : 4.730000
문자값 출력 : B

C++에서는 오버로딩이 가능해 같은 이름으로 함수를 만들 수 있다.

#include <iostream>

using namespace std;

int Add(int a, int b);
double Add(double a, double b);
char Add(char a, char b);

int main()
{
    int i;
    double d;
    char c;

    i = Add(10, 20);
    d = Add(3.14, 1.59);
    c = Add('A', char(1));    
    printf("정수값 출력 : %d\n", i);
    printf("실수값 출력 : %f\n", d);
    printf("문자값 출력 : %c\n", c);
}

int Add(int a, int b)
{
    return a + b;
}
double Add(double a, double b)
{
    return a + b;
}
char Add(char a, char b)
{
    return a + b;
}
정수값 출력 : 30
실수값 출력 : 4.730000
문자값 출력 : B

템플릿코드를 사용할 경우 더 간단하게 만들 수 있다. 보통 프레임워크 개발자나 엔진 개발자들이 이용한다.

#include <iostream>

using namespace std;

template <class T> T Add(T a, T b);

int main()
{
    int i;
    double d;
    char c;

    i = Add(10, 20);
    d = Add(3.14, 1.59);
    c = Add('A', char(1));    
    printf("정수값 출력 : %d\n", i);
    printf("실수값 출력 : %f\n", d);
    printf("문자값 출력 : %c\n", c);
}

template <class T> T Add(T a, T b)
{
    return a + b;
}

클래스(Class)

사용자가 정의한 추상적인 데이터형(Abstract Data Type)

클래스는 C언어의 구조체와 비슷한 형태이며, 멤버 변수와 멤버 함수로 구성된다.

class 클래스 이름
{
	접근 지정자:
    	데이터형 멤버변수;
	접근 지정자:
    	데이터형 멤버함수;
}

접근 지정자

클래스는 멤버 선언 시 접근 권한을 설정한다.
private : 접근 불가
public : 접근 가능
protected : 자식은 접근 가능하지만, 외부에서는 접근 불가능

멤버함수 접근

#include <iostream>
using namespace std;

// 클래스 정의
class MousePoint
{
    private : // 외부에서 접근하지 못하게 함
        int x, y;

    public :
        void SetXY(int nX, int nY);
};

// 멤버함수 구현
void MousePoint::SetXY(int nX, int nY)
{
    x = nX;
    y = nY;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
}

// 객체 생성
int main()
{
    MousePoint point; // 객체
    point.SetXY(10, 20);
}
x = 10
y = 20

MousePoint 클래스에서 멤버변수 x, yprivate로 막혀있기 때문에, 객체에서 변수에 접근하기 위해서 멤버함수 SetXY를 통해야한다.

생성자와 소멸자

생성자(constructor)

초기화

초기화란 기본 데이터를 선언과 동시에 초기값을 대입하는 것이다.

int a = 5;
float b = 10.5;
int c[5] = {1, 2, 3, 4, 5};

변수 선언 후에 값의 할당이 이루어지는 경우 초기화라고 하지 않는다

int a;
a = 5;

생성자의 필요 이유

클래스 생성 시 매번 반복되는 초기화 멤버 함수를 만들어야 한다. 객체 생성 시 자동으로 초기화해주는 초기화 전용함수가 있는데, 이 함수를 생성자(constructor)라고한다.

생성자의 특징

  • 생성자의 이름은 클래스의 이름과 동일
  • 생성자 타입 지정하지 않음
  • 생성자의 호출은 객체 선언 시 자동으로 호출. 인위적 호출 안됨
  • 반환값을 지정하지 않음
  • 디폴트 생성자가 존재

생성자도 오버로딩이 가능하다는 것을 기억하자.

소멸자(destructor)

객체가 소멸할 때 자동 호출되는 소멸자가 존재한다.

소멸자의 특징

  • 소멸자도 클래스의 이름을 그대로 사용한다. 맨 앞에 틸트~기호 표기
  • 소멸자의 타입 지정 안함
  • 객체 소멸 시 자동 호출. 인위적 호출 금지
  • 반환값을 지정하지 않음
  • 전달인자 지정 안함
  • 소멸자는 생성자처럼 오버로딩 안됨
#include <iostream>
using namespace std;

// 클래스 정의
class MousePoint
{
    private : // 외부에서 접근하지 못하게 함
        int x, y;

    public :
        void SetXY(int nX, int nY);
        MousePoint(); // 디폴트 생성자
        MousePoint(int nX, int nY); // 생성자
        ~MousePoint(); // 소멸자
};

void MousePoint::SetXY(int nX, int nY) // 멤버함수
{
    x = nX;
    y = nY;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
}

MousePoint::MousePoint() // 디폴트 생성자
{
    cout << "생성자 호출" << endl;
    x = 10;
    y = 20;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
}

MousePoint::MousePoint(int nX, int nY) // 생성자
{
    x = nX;
    y = nY;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
}

MousePoint::~MousePoint() // 소멸자
{
    cout << "소멸자 호출" << endl;
}

// 객체 생성
int main()
{
    MousePoint point; // 객체
}
생성자 호출
x = 10
y = 20
소멸자 호출

생성자는 오버로딩이 가능하다.

클래스의 특징과 객체 활용

객체 배열

다수의 변수 사용시 배열을 선언한 것처럼 객체 또한 배열로 선언이 가능한데, 이를 객체 배열이라고 한다.

#include <iostream>
using namespace std;

// 클래스 정의
class MousePoint
{
    private : // 외부에서 접근하지 못하게 함
        int x, y;

    public :
        void SetXY(int nX, int nY);
        MousePoint(); // 디폴트 생성자
        MousePoint(int nX, int nY); // 생성자
        ~MousePoint(); // 소멸자
        
        // private한 x,y값을 출력
        int GetX(){return x;}
        int GetY(){return y;}
};

// 멤버함수 구현
void MousePoint::SetXY(int nX, int nY)
{
    x = nX;
    y = nY;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
}

MousePoint::MousePoint() // 디폴트 생성자
{
    cout << "생성자 호출" << endl;
    x = 10;
    y = 20;
    // cout << "x = " << x << endl;
    // cout << "y = " << y << endl;
}

MousePoint::MousePoint(int nX, int nY) // 생성자
{
    x = nX;
    y = nY;
    // cout << "x = " << x << endl;
    // cout << "y = " << y << endl;
}

MousePoint::~MousePoint() // 소멸자
{
    cout << "소멸자 호출" << endl;
}

// 객체 생성
int main()
{
    MousePoint pt[3] = {MousePoint(10, 20), MousePoint(30, 40), MousePoint(50, 60)};
    // pt[0].x = 10, pt[0].y = 20  ....

    for (int i = 0; i < 3; i++)
    {
        cout << pt[i].GetX() << endl;
        cout << pt[i].GetY() << endl << endl;
    }
}
10
20

30
40

50
60

소멸자 호출
소멸자 호출
소멸자 호출

객체 포인터

객체의 주소값을 저장하기 위한 변수로, 객체를 간접 참조하기 위해 사용한다.

MousePoint *pObj;
MousePoint pt(10,20)
pObj = &pt;
profile
Done is better than perfect

0개의 댓글