상향형변환(업캐스팅):
부모가 자식에게 접근
class A{run();}
class B : public A{run();run2();}
main{A *obj = new B();} => obj는 run은 사용 가능 (업캐스팅은 보통 주소(*) 쓰면서 객체 생성), run2는 사용 불가능
포인터로 객체 선언하고 쓰려면 obj.run(); 이런식이 아니라 obj->run(); 이렇게 씀
참조 업캐스팅:
B o1; //객체생성
A& o2 = o1; //참조 업캐스팅
-> 이러면 o2.run(); 이렇게 .으로 함수 실행함
하향형변환(다운캐스팅):
자식이 부모에게 접근
자식에게만 있는 run2(); 사용을 위해서 부모타입에 참조되있는 인스턴스를 다시 자식타입으로 형변환
A *obj = new B(); //업캐스팅
B* obj2 = (B*)obj; //다운캐스팅
obj2 -> run2(); A에 run2가 없어도 가능
or
B& obj2 = (B&)*obj;
obj2.run2();

다운캐스팅 예제
Shape *ps = new Rectangle(); // 업캐스팅
Rectangle *pr = (Rectangle *) ps; // pr로 다운캐스팅 객체 생성
pr->setWidth(100);
or
((Rectangle *) ps)->setWidth(100); // 한번만 사용할때 한번에 다운캐스팅
순수가상함수: 몸체({}) 없이 헤더만 존재하는 함수. 인터페이스 역할 (순수가상함수에서 정의도 가능하긴함)
abstract 클래스: 순수가상함수 하나 이상 가지고 있는 클래스
class [클래스이름] {
public:
virtual 반환형 함수이름(매개변수) = 0;
}
사용자 정의 타입(예: 클래스, vector)도 기본 타입처럼 +, ==, << 같은 연산자를 사용할 수 있도록 해준다.
ex) a+b에서 +를 직접 정의함
불가능한거
::(범위지정 연산자)
.(멤버 선택 연산)
.*(멤버 포인터 연산자)
?:(조건 연산자)
멤버 함수로 구현
[반환형] operator[연산자(ex:+, ==)]([const 클래스& 매개변수]) {}
ex) bool operator==(const MyClass& other) {};
비멤버 함수(전역 함수)로 구현
ex) friend Point operator+(const Point& p1, const Point& p2);

연산자가 비교목적(==,!=)이면 반환형 bool, 산술 목적(+,-,*,/)으로 새로운 값을 리턴하려면 반환형 클래스 객체를 사용, 복합 대입 목적(+=,-=)으로 내 값을 바꾸려면 반환형 클래스 객체 참조(&) 사용
비교(bool)

산술


산술 전위,후위 증가 비교

전위는 매개변수 없음, 후위는 int 매개변수 사용
전위 증가는 자신을 반환해서 &가 붙음. (this 반환)
후위 증가는 증가 전 값의 복사본을 반환해야 되서 &가 안 붙음.
복합 대입

ostream <<
피연산자가 ostream(사용자 정의 타입이 아닌 기본 타입)이기 때문에, 무조건 비멤버 함수로 정의해야됨(private에 접근해야돼서)
cout를 객체 타입으로 생각해야됨.
멤버 함수면 [객체].operator <<(cout,[객체])

class Point {
private:
int x, y;
public:
Point(int x = 0, int y = 0) : x(x), y(y) {}
friend ostream& operator<<(ostream& os, const Point& p);
};
ostream& operator<<(ostream& os, const Point& p) {
os << "(" << p.x << ", " << p.y << ")";
return os; // 반드시 os를 반환해야 연속 출력 가능
}
//main에서 cout << p1;

외워야 할 규칙 정리


클래스의 내부 데이터에 접근할 수 있는 특수한 함수
friend void [함수이름]([자신 클래스이름] [매개변수]);
프렌드 함수 특징
예시)

프렌드 함수는 클래스 외부에 선언되어서 전역함수 처리로 됨(비멤버 함수)
프렌드 클래스


예외처리 - 표준 예외 클래스, 기본형, 사용자 정의 클래스, 모든 예외(...)
사용자 정의 클래스 예외, 표준 예외 클래스 뒤에 & 붙임
여러 종류의 예외 처리하기 위해서
텍스트 파일: 아스키 코드(헥스코드가 아스키 코드)
이진 파일: 숫자 자체를 바이트로 저장(헥스코드가 바이트)
템플릿 함수
자료형 다른 함수 오버로딩일때 자료형 관계없이 처리되는 함수
-라이브러리
컨테이너: 자료 저장(벡터, 리스트, 맵, 집합, 큐, 스택)
반복자: 컨테이너 안에 저장된 요소들을 순차적으로 처리
알고리즘: 정렬이나 탐색 같은 알고리즘 구현
장점
순차 컨테이너
벡터: 동적 배열 처리, 뒤에서 자료 추가
데크: 벡터와 비슷, 앞에서도 자료 추가 가능
리스트: 중간에서 자료 추가 가능
연관 컨테이너
(자동 정렬-오름차순)
집합(set): 중복 없는 자료 정렬(단일)
다중 집합(multiset): 중복 허용 집합
맵: 중복 없는 키-값 형식(쌍)
다중 맵: 중복 허용 맵
컨테이너 어댑터
스택(후입선출), 큐(선입선출), 우선순위큐


다이나믹 캐스트를 위해서 부모가 꼭 virtual이어야 한다.
객체 타입이 올바르면 반환, 그렇지 않으면 null 반환

다운 캐스팅 안전하게 하기 위해
업캐스팅 시 부모 클래스 함수와 자식 클래스 함수의 이름 같으면 부모 클래스의 함수가 호출됨.
부모 클래스 함수에 virtual 써서 정의하면 자식 함수(부모 함수와 이름 같은)가 호출됨 = 자식클래스가 오버라이딩 한거
virtual void obj(){cout << "~~";}
virtual 반환형 함수이름(매개변수) = 0; //(순수 가상함수)
catch (...){} //모든 예외
예외 잡을거 없으면 -> std::terminate() 종료
하나의 인자를 가지는 생성자로, 다른 타입의 값을 해당 클래스 타입으로 자동 변환해주는 생성자
template <typename T>
T add(T a, T b) {
return a + b;
}
template <>
int add<int>(int a, int b) {
cout << "int" << endl;
return a + b;
}
#include <stack>
stack<int> s;
s.push(x)
s.pop()
s.top()
s.empth() //비어있는지
#include <queue>
stack<int> q;
q.push(x)
q.pop() // front 제거
q.front() //꺼내는 용도
q.back() //넣는 용도
q.empth() //비어있는지
부모에 virtual로 선언
Animal* a1 = new Dog();
a1->speak();
이러면 virtual로 선언해서 자식의 speak() 실행