'현실세계에 있는 모든 사물을 프로그램화 시키겠다'
구조적 프로그래밍 방식
순차적 프로그래밍 방식 / 하향식 및 폭포수 방식이라고 한다.
기능적인 기본 단위는 함수이다.
객체 지향 프로그래밍 방식
기능 단위는 객체이다.
사용자의 요청에 의해 처리되는 구조이다.
대표적인 예는 모든 윈도우 프로그램이다.
이벤트 기반 프로그램은 전부 다 객체 지향이다.
구조적 프로그래밍은 설계가 잘못되면 중간에 수정할 수 없다.
객체 지향 프로그래밍은 중간에 수정할 수 있는 구조를 지향한다.
처음에 자세하게 설계하지 않고 점차 구체화가 된다.
상속구조를 통해서 유연한 구조를 만든다.
사용자가 직접 사용자 정의 타입을 만들어 하나의 데이터 단위로 처리
가장 대표적인 예는 구조체 타입
플라톤의 이데아는 추상화 개념과 일맥 상통한다.
플라톤은 개라는 개, 나무라는 나무가 존재하고 있다고 말한다.
개의 본질 개의 원형은 이데아의 세계, 관념의 세계에 존재한다.
동굴에서 불빛으로 개를 비춰 그림자를 보면 개의 원형에 따라서 여러 종류의 개로 보인다.
"원형을 기반으로 해서 여러 자식 객체들이 만들어질 수 있다."
① 객체 지향에서는 기본적으로 데이터는 숨긴다. 즉, 보안적으로 데이터를 은닉시킨다.
② 그 데이터를 조작할 수 있는 인터페이스가 필요하다.
클래스에 종속되어있는 함수를 클래스라고 부른다.
클래스는 데이터와 메소드로 이루어져 있고 데이터는 기본적으로 숨겨져있다.
이 데이터는 메소드를 통해서만 조작할 수 있어야 한다.
대표적으로 부모가 자식에게 유산을 상속하는 경우의 예
생물 분류법으로써의 개념
프로젝트 관점에서의 상속 개념
수평적으로 여러개가 겹쳐서 뜨는 현상.
int Add(int a)
int Add(char a, char b)
수직적이다.
기존의 기능을 덮어버린다.
#include <iostream>
void main()
{
std::cout << "Hello C++" << std::endl;
}
출력결과
Hello C++
io : input output의 약자
stream : 흘러간다
'입력, 출력 값이 흘러가게 하는 라이브러리'
<< : cout이라는 객체의 방향으로 집어 넣는다.
cout : 모니터와 연관있는 객체
endl : endline, 개행
std : 이름 공간(name space)의 객체
:: : 스코프 연산자(영역 결정 연산자)
'std 안에 속해있는 cout'
'std안에 속해있는 endl'
#include <iostream>
void main()
{
int a = 10;
double b = 3.14;
char c = 'A';
std::cout << a << std::endl;
std::cout << b << std::endl;
std::cout << c << std::endl;
//std::cout << "Hello C++" << std::endl;
}
같은 이름의 대상이 있다고 할 때는 호출의 대상이 명확하지 않음.
#include <iostream>
void func()
{
std::cout << "A학급 주성" << std::endl;
}
void func()
{
std::cout << "B학급 주성" << std::endl;
}
void main()
{
func();
}
이런 코드를 실행시킨다고 했을 때, 이미 선언된 함수라는 오류가 난다.
오버로딩이 되려면 매개변수의 타입이나 개수가 달라야 함!
이런 상황을 namespace를 활용해 해결한다.
#include <iostream>
namespace A
{
void func()
{
std::cout << "A학급 주성" << std::endl;
}
}
namespace B
{
void func()
{
std::cout << "B학급 주성" << std::endl;
}
}
void main()
{
A::func();
B::func();
}
출력결과
A학급 주성
B학급 주성
A영역에 속해있는 func()
B영역에 속해있는 func()라고 이해하면 된다.
결국 std::cout도 std라는 namespace 안에있는 cout을 사용하겠다는 의미이다.
using namespace std;
void main()
{
int a = 10;
cout << a << endl;
}
using namespace를 사용하면 std 이름을 써주지 않아도 된다.
입력 객체, 입력 디바이스와 연결이 되어 있다.
cin >> a; // scanf
'a에 입력을 받아서 a에 넘겨주겠다.'
C언어처럼 주소값을 입력해주지 않아도 알아서 찾아간다.
#include <iostream>
using namespace std;
void main()
{
int a = 0;
double b = 0;
cin >> a; // scanf
cout << "정수 출력 : " << a << endl;
cin >> b;
cout << "실수 출력 : " << b << endl;
}
출력결과
100
정수 출력 : 100
3.14
실수 출력 : 3.14
int a;
for(a = 0; a < 100; a++)
{
...
}
for(a = 0; a < 100; a++)
{
...
}
참고: 변수 선언의 자유로움으로 인해 무분별하게 선언하면, 코드의 유지보수 시 관리가 제대로 안 될 수 있는 우려가 생긴다.
선언부
void func(int a, int b);
호출부
func(10,20);
// 매개변수 값은 각각 10과 20
선언부
void func(int a = 10, int b = 20);
호출부1
func(100,200);
// 전달인자의 값은 각각 100과 200
호출부2
func(50);
func();
// 첫 번째 전달인자 50, 두 번째 전달인자 생략 (50,20)
// 첫 번째, 두 번째 전달인자 모두 생략 (10,20)
using namespace std;
void func(int a = 10, int b = 20);
void main()
{
func();
func(100);
func(100, 200);
}
void func(int a, int b)
{
cout << "두 전달인자 출력 : " << a << " " << b << endl;
}
출력결과
두 전달인자 출력 : 10 20
두 전달인자 출력 : 100 20
두 전달인자 출력 : 100 200
#include <iostream>
using namespace std;
int nTemp = 10;
void main()
{
{
int nTemp = 20;
cout << "nTemp = " << nTemp << endl;
cout << "::nTempt = " << ::nTemp << endl;
}
cout << "nTemp = " << nTemp << endl;
}
출력결과
nTemp = 20
::nTempt = 10
nTemp = 10
:: 앞에 아무것도 없으면 소속이 없는 '전역'을 의미한다.
인라인 함수란
코드 라인 자체가 호출부 안에 포함된다는 의미
#define 매크로의 단점을 보완하고, 일반 함수 호출의 부하를 덜어줌
인라인 함수의 장점
인라인 함수의 단점
#define을 사용하면 전처리, 즉 컴파일 전에 실행할 수 있다.
개념: 스타크래프트의 오버로드처럼 똑같은 여러 개의 오버로드가 존재하지만 그 안에 탑승한 유닛들은 각각 다르다.
함수의 오버로딩이란 똑같은 이름의 함수들이 존재하지만 매개변수 타입이나 개수 차이에 의해서 서로 다른 함수로 구분된다.
C언어에서는 불가능하다.
⇛ 전달인자의 이름으로 보지않고 함수의 이름을 기준으로 보기 때문에 같은 함수이름이면 오류가 난다.
두 수를 더하는 기능으로서는 똑같은데 이름만 다른 모습은 바람직하지 않다.
#include <iostream>
using namespace std;
int Add(int a, int b);
double Add(double a, double b);
char Add(char a, char b);
void main()
{
int i;
double d;
char c, ch = 1;
i = Add(10, 20);
d = Add(3.14, 1.59);
c = Add('A', ch);
cout << "정수값 출력 : " << i << endl;
cout << "정수값 출력 : " << d << endl;
cout << "정수값 출력 : " << c << endl;
}
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.73
정수값 출력 : B
전달인자는 반드시 달라야한다.
'클래스의 본질은 데이터 타입이다.'
구조체와 클래스의 큰 차이점은 구조체는 변수로 이루어져있지만, 클래스는 (멤버)변수와 (멤버)함수가 혼재되어있다는 점이다.
구조체도 함수를 가질 수는 있지만 보안의 개념이 없어서 구조체 멤버에 바로 접근하면 된다. 함수가 필요가 없어서 쓰지 않는 것이다.
클래스는 멤버 변수에 접근하기 위한 메소드라고도 부르는 멤버함수가 있어야 한다. 객체지향에서는 기본적으로 보안때문에 데이터를 은닉하기 때문이다.
클래스의 멤버 선언 시 접근 권한을 설정한다.
접근 권한에는 private, protected, public 3가지가 있다.
protected는 상속 개념 이후에 배우도록 하겠다.
현재 클래스: 나
private: 클래스 내에서만 접근 가능하고, 외부에서 절대 접근할 수 없는 권한이다. 캡슐화와 데이터 은닉 철학에 부합한다.
public: 클래스 내에서 뿐만 아니라 외부에서도 접근이 가능한 권한이다. 데이터의 은닉이 되지 않는다.