C++
C++은 1980년대 초에 개발된 언어입니다(공식 발표는 ISO.IEC 14882:1998, 1998년). 기존언어와의 차이점은:
- OOP(Object-Oriented Programming): 클래스 문법 - 캡슐화, 상속, 다형성을 지원
- 표준 라이브러리: 함수 형태 제공(X), 컨테이너 클래스(구조화된 클래스) 제공(방대함)
- 예외처리: 오류처리, 유지보수 등 지원
CPP문법은 C보다 좀 더 큰 프로젝트를 관리할 수 있도록 구조화된 언어입니다. 따라서 C언어에서 명령어 묶어서 함수로 관리했다면, C++에서는 함수와 변수를 클래스로 묶어 관리합니다.(클래스 = 함수 + 변수)
typedef struct { string name; string (*getName)(void*); void (*setName)(void*, string); }HUMAN;
클래스
접근제어
CPP = 객체지향 = 클래스 = 캡슐화(Encapsulation)란 다음을 목료로 합니다.
- 정보 은닉(Information Hiding)
- 모듈화(Modularity)
하나의 객체는 하나의 완성된 목표를 갖아야 하며, 내부적인 구체적인 모습을 가림으로써, 비정상적인 접근과 제어를 최대한 통제하고, 제어점을 단순화하게 됩니다. 제공자는 이러한 인터페이스에 대해 정확하게 기술해야하는 의무가 있습니다.
하위 객체를 접근할 때, .(dot)연산자를 사용합니다. 접근제어자는 인터페이스의 접근권한을 기술하는 언어입니다.
접근제어자 | 내용 |
private | 클래스 내부에서만 접근 가능 |
protected | 상속된 클래스까지 접근 가능 |
public | 모두가 접근 가능 |
class A { private: int val1; protected: int val2; public: int val3; }
friend
접근제어자를 공유할 수 있는 키워드 입니다.
class A { friend class B; }
this
this는 스스로를 가리키는 예약어입니다. 아래 예시는 멤버 변수가 받은 argument와 멤버 변수의 구분을 하는 예시입니다.
void setName(string name) { this->name = name; }
생성자/소멸자
생성자와 소멸자는 객체가 생성 소멸될 때, 자동으로 호출되는 함수입니다.
- 생성자: 클래스명과 동일한 멤버함수, 오버로딩 가능
- 소멸자: ~로 시작하면서 클래스명과 동일한 멤버함수, 소멸자가 호출되는 시기는 클래스가 소멸하는 시기
class Example { public: Example() { ... } Example(int value) { ... } ~Example() { ... } }
연산자 재정의
객체지향 코드를 수행하면서, 객체는 인간의 인식과 흡사하게 구성하면 관리면에서 유리해집니다. 예를들어, A반과 B반이 더한다면, 생물학적으로 융합된다기 보다, 인원이 합쳐진다고 인식하는 편입니다.
연산자의 재정의는 해당 객체에서 연산자가 수행할 동작을 구체적으로 명기합니다.
class school {} school operator+( ... ) { ... }
클래스 프로토타입
클래스 프로토타입을 사용할 수 있습니다.
class A; <- 프로토타입
class B { A a; };
class A {};
상속
구조화, 코드 재사용과 관련하여 크고 복잡한 객체를 한 번에 생성하는 것은 어려운 일일 것입니다. 작고 간단한 구조를 연결하는 방법(문법)을 제시합니다.
Extends
- 상속받을 때, 콜론(:)을 사용합니다.
class 부모 { ... } class 자식 : 접근제어자 부모 { ... }
- 복수의 상속을 받을 수 있습니다.(다중 상속)
- 상속시 접근제어자로 인해 내부 멤버의 접근이 변경 될 수 있습니다.
기존 접근제어자 public 상속 protected 상속 private 상속생략시 그대로 상속 모두 protected 모두 private public public protected private protected protected protected private private 접근금지 접근금지 private
class 부모 { ... } class 자식 : 접근제어자 부모1 , 접근제어자 부모2 ... { ... }
Override
당연하게도 자식객체는 언제나 부모객체 이상의 기능을 갖습니다. 상속이 복잡해 질수록 구조의 관리가 어려워 질 수 있습니다. 만약 자식객체의 기능이 부모객체의 기능을 약간 수정해서 쓴다면 새로 함수를 정의할 필요가 없어집니다. override(오버라이드)의 문법은 overload(오버로드)의 문법과 동일합니다. 동일한 함수명일 때, 호출되는 위치에 따라서 호출되는 함수를 선택할 수 있습니다. 내가 "아빠"를 부를 때와, 당신이 "아빠"를 부를 때, 대상은 동일하지 않지만 우리는 특정할 수 있습니다.
- 오버로딩(overloading) : 동일한 함수명 + 다른 전달인자(argument)를 갖는 함수를 여러개 정의
- 오버라이딩(overriding) : 동일한 함수명 + 같은 전달인자(argument)를 갖는 함수를 상속받은 클래스에서 재정의
class A {
public:
void override();
}
class B : public A {
public:
void override(); // 재정의 된 함수
}
Super
만약 부모객체의 멤버객체를 사용하려면,
- Visual Studio 에서: "__super"" 키워드를 사용
- GDB(VS code) 에서: "부모객체::"를 사용
Virtual
가상함수는 동적 다형성의 개념으로 인해, 언제든 재정의(override) 될 수 있음을 선언하게 됩니다. 내용이 없는 경우(= 0으로 정의) '순수 가상 함수'(Pure Virtual Function)라고 합니다.
다형성(Polymorphism)은 자녀객체가 부모객체의 역할을 모두 수행할 수 있는 장점을 이용해서, 코드내에서 형 변환 없이 유연하게 사용가능 한 개념입니다.
추상클래스(Abstract Class)
추상클래스는 한 개 이상의 순수 가상 함수를 갖는 클래스를 의미합니다.
virtual string act() = 0;
Multi Extends
다중 상속을 위해서 ,(콤마)연산자를 사용합니다.
class 부모 { ... } class 자식 : 접근제어자 부모1 , 접근제어자 부모2 ... { ... }
UML
Class 관계 | 번역 | UML표현 | 설명 | 예시 |
Generalization | 일반화 | B A | 상속(new generation)관계 입니다. |
class A; class B : public A; |
Association | 연관 |
양방향 : B A |
다른 클래스를 데이터 교환수단으로 활용 합니다. |
class A { void get(B b); } class B { void get(A a); } |
단방향 : B A |
class A; class B { void get(B b); } |
|||
Dependency | 의존 | B A | 독립된 객체간에 정보 정보교환이나 서비스를 사용합니다. |
class A { do(); } class B { A &a; a.do(); } |
Aggregation | 집합 | B A | 다른 클래스의 데이터를 직접 소유합니다. |
class A; class B { A *a; void getA(A *a) { this.a = a }; } |
Composition | 합성 | B A | 멤버함수로 갖습니다. (원개념) 객체의 소멸주기가 소유한 객체에 종속되어 있습니다. |
class A; class B { A a; } |
Realization | 실체화 | B A | 추상클래스를 상속받습니다. |
class A { virtual void foo() = 0; } class B : public A; |