C++ 유도 클래스에서 출력 연산자 사용하기
·
C++/Class
유도 클래스에서 출력 연산자 사용하기 연산자 오버로딩할 때만 사용하는게 아니라, 다형성을 더 유연하게 구현할 때도 사용되는 기법이다. 예제 멤버 함수로 만들 수 없는 연산자를 오버라이딩한 것 처럼 구현하기 위해서 다음과 같은 기법을 사용할 수 있다. print 함수를 오버라이딩하고, 연산자 오버로딩을 할 때 이를 호출하는 방식이다. #include class Base { public: friend std::ostream& operator
C++ 동적 형변환 (Dynamic Casting)
·
C++/Class
동적 형변환 (Dynamic Casting) dynamic_cast는 캐스팅이 실패하면 nullptr를 반환한다. 예제 간단한 예제 #include class Base { public: int i_ = 0; virtual void print() { std::cout
C++ 객체 잘림 (Object Slicing)
·
C++/Class
객체 잘림 (Object Slicing) 부모 클래스 자료형에 자식 클래스 자료형을 대입할 경우, 흔히 말하는 truncation이 발생한다. 예제 #include class Base { public: int i_ = 0; virtual void print() { std::cout
C++ 다이아몬드 상속 (Diamond Polymorphism)
·
C++/Class
다이아몬드 상속 (Diamond Polymorphism) 한 자식 클래스가 상속받는 서로 다른 부모 클래스들이, 같은 조부모 클래스를 상속받는 구조 예제 클래스 A를 B, C가 상속받은 후 D가 B와 C를 상속받으면, D::B::A와 D::C::A가 각각 존재하게 된다. #include class PoweredDevice { public: int i_; PoweredDevice(const int& power) { std::cout
C++ 인터페이스 클래스 (Interface Class)
·
C++/Class
인터페이스 클래스 (Interface Class) 순수 가상 함수를 이용하여 만드는 클래스 특별한 기능을 하지는 않고 자식 클래스들을 편하게 다루기 위해 사용한다. 예제 #include class IErrorLog { public: virtual ~IErrorLog() {} virtual bool reportError(const char* errorMessage) = 0; }; class FileErrorLog : public IErrorLog { public: bool reportError(const char* errorMessage) override { std::cout
C++ 추상 기본 클래스 (Abstract class)
·
C++/Class
추상 기본 클래스 (Abstract class) 순수 가상 함수가 하나라도 존재하는 클래스 순수 가상 함수가 존재하는데 오버라이딩하는 함수가 없을 경우, 에러가 발생한다. 예제 #include class Animal { protected: std::string name_; public: Animal(const std::string &name_in) : name_(name_in) {} std::string getName() { return name_; } virtual void speak() const = 0; // pure virtual function }; class Cat : public Animal { public: Cat(const std::string& name_in) : Animal(name_..
C++ 순수 가상 함수 (Pure Virtual Function)
·
C++/Class
순수 가상 함수 (Pure Virtual Function) body가 없고 값이 0으로 설정된 virtual 함수를 의미한다. body를 외부에서 정의할 수는 있는데 의미는 없다. 예제 #include class Animal { protected: std::string name_; public: Animal(const std::string &name_in) : name_(name_in) {} std::string getName() { return name_; } virtual void speak() const = 0; // pure virtual function }; class Cat : public Animal { public: Cat(const std::string & name_in) : Animal..
C++ 가상 (함수) 테이블 (Virtual Tables)
·
C++/Class
가상 (함수) 테이블 (Virtual Tables) virtual 키워드를 사용하면 내부적으로 가상 테이블의 주소가 저장된다. 예제 간단한 상속 예제 class Base { public: // FunctionPointer *_vptr; virtual void func1() {} virtual void func2() {} }; class Derived : public Base { public: // FunctionPointer *_vptr; virtual void func1() {} }; 여기서 클래스들의 가상 테이블은 다음과 같다. Base VTable 가리키고 있는 함수 func1 Base::func1 func2 Base::func2 Derived VTable 가리키고 있는 함수 func1 Derive..
C++ 동적 바인딩 (Dynamic Binding)
·
C++/Class
동적 바인딩 (Dynamic Binding) Late Binding 정적 바인딩보다 느리다. 대신 프로그래밍이 좀 더 유연해진다. 런타임에 주소를 쫓아가서 함수를 실행시키는 경우이다. 예제 #include int add(int x, int y) { return (x + y); } int subtract(int x, int y) { return (x - y); } int multiply(int x, int y) { return (x * y); } int main() { using namespace std; int x, y; cin >> x >> y; int op; cout > op; int(*func_ptr)(int, int) = nullptr; switch (op) { case 0: func_ptr = ..
C++ 정적 바인딩 (Static Binding)
·
C++/Class
정적 바인딩 (Static Binding) Early Binding 동적 바인딩보다 빠르다. 빌드 타임에 모든 변수명이나 함수명이 정의된 경우이다. 예제 #include int add(int x, int y) { return (x + y); } int subtract(int x, int y) { return (x - y); } int multiply(int x, int y) { return (x * y); } int main() { using namespace std; int x, y; cin >> x >> y; int op; cout > op; int result = 0; switch (op) { case 0: result = add(x, y); break; case 1: result = subtrac..
C++ 가상 소멸자
·
C++/Class
가상 소멸자 virtual 키워드를 소멸자에도 붙일 수 있다. 예제 가상 소멸자를 사용하지 않은 기본 예제 #include class Base { public: ~Base() { std::cout
C++ 공변 반환형(Covariant Return Type)
·
C++/Class
공변 반환형(Covariant Return Type) 포인터나 레퍼런스의 전달에서, 상속 관계의 클래스 반환 자료형에 관한 내용이다. 예제 다음은 가상 멤버 함수 getThis로 받은 포인터를 통해 일반 멤버 함수 print를 호출하는 예제이다. #include class A { public: void print() { std::cout
C++ Override, Final
·
C++/Class
Override, Final Override 부모 클래스에서 virtual로 선언한 함수를 자식 클래스에서 오버라이딩한다는 의미의 키워드이다. 컴파일러는 프로그래머의 의도를 정확하게 알 수 없기 때문에, 다음과 같이 프로그래머가 실수할 수 있는 상황이 생긴다. 예제 print 함수를 오버라이딩하려는데, 실수로 파라미터를 int가 아닌 short로 작성한 상황이다. #include class A { public: virtual void print(int x) { std::cout
C++ 가상 함수와 다형성 (virtual)
·
C++/Class
가상 함수와 다형성 (virtual) 상속 최상위 클래스에서 멤버 함수를 정의할 때 virtual 키워드를 사용하면, 가장 말단까지 오버라이딩된 함수를 찾아서 실행한다. #include class A { public: virtual void print() { std::cout
C++ 다형성의 기본 개념
·
C++/Class
다형성의 기본 개념 부모 클래스의 포인터로 자식 클래스의 주소를 가리키면, 부모 클래스의 인스턴스로 인식한다. 예제 자식 클래스에서 멤버 함수를 오버라이딩해도, 부모 클래스의 포인터에서 접근하면 부모 클래스의 멤버 함수가 호출된다. #include class Animal { protected: std::string name_; public: Animal(const std::string & name_in) : name_(name_in) {} std::string getName() { return name_; } void speak() const { std::cout
C++ 다형성 (Polymorphism)
·
C++/Class
다형성 (Polymorphism) 다형성의 기본 개념 가상 함수와 다형성 override, final 공변 반환형(Covariant Return Type) 가상 소멸자 (Virtual Destructor) 정적 바인딩 (Static Binding) 동적 바인딩 (Dynamic Binding) 가상 테이블 (Virtual Tables) 순수 가상 함수 (Pure Virtual Function) 추상 기본 클래스 (Abstract class) 인터페이스 클래스 (Interface Class) 다이아몬드 상속 (Diamond Polymorphism) 객체 잘림 (Object Slicing) 동적 형변환 (Dynamic Casting) 유도 클래스에서 출력 연산자 사용하기
C++ 다중 상속
·
C++/Class
다중 상속 여러 클래스에서 상속을 받을 수 있다. #include class USBDevice { int id_; public: USBDevice(int id_in) : id_(id_in) {} int getID() { return id_; } void plugAndPlay() {} }; class NetworkDevice { int id_; public: NetworkDevice(int id_in) : id_(id_in) {} int getID() { return id_; } void networking() {} }; class USBNetworkDevice : public USBDevice, public NetworkDevice { public: USBNetworkDevice(int usb_id, i..
C++ 상속받은 멤버의 접근 권한 변경
·
C++/Class
상속받은 멤버의 접근 권한 변경 using 키워드 사용 #include class Base { protected: int i_; }; class Derived : public Base { public: using Base::i_; }; int main() { using std::cout; using std::endl; Derived d; d.i_ = 1024; cout
C++ 함수 오버라이딩
·
C++/Class
함수 오버라이딩 자식 클래스에서 부모 클래스의 함수명과 같은 함수를 정의할 수 있다. 함수 오버로딩과 비슷하다. 호출하는 클래스에 따라 결정된다는 점이 다르다. 예제 함수 오버라이딩 #include class Base { public: void print() { std::cout
C++ 상속과 접근 지정자
·
C++/Class
상속과 접근 지정자 상속 적용 시 부모 클래스 앞에 public, protected, private와 같은 접근 지정자를 붙인다. 자식 클래스에서 기본적으로 부모 클래스의 멤버들을 어떤 권한으로 받아들일지에 관한 것이다. 예제 아래 예제의 경우 public으로 상속받았으므로 멤버들의 기본 접근 권한이 public이 된다. protected, private은 public보다 보안이 더 강하므로 그대로 적용된다. #include class Base { public: int public_; protected: int protected_; private: int private_; }; class Derived : public Base { }; int main() { using namespace std; Deri..
C++ 상속과 패딩
·
C++/Class
상속과 패딩 일반적인 구조체와 마찬가지로 패딩이 끼게 된다. 패딩이 없는 예제 (int, float) #include class Mother { int i_; public: Mother(const int & i_in = 0) : i_(i_in) { std::cout
C++ 유도된 클래스들의 소멸 순서
·
C++/Class
유도된 클래스들의 소멸 순서 말단(자식)부터 소멸된다고 생각하면 된다. #include class A { public: A(int a = 1024) { std::cout
C++ 유도된 클래스들의 생성 순서
·
C++/Class
유도된 클래스들의 생성 순서 당연하게도 부모 클래스부터 생성된다. #include class Mother { int i_; public: Mother() : i_(1) { std::cout
C++ 상속 Teacher-Student 예제
·
C++/Class
상속 Teacher-Student 예제 상속을 사용하지 않은 원본 예제 Teacher, Student 클래스의 공통 멤버인 name_, setName, getName을 묶어서 Person이라는 클래스를 만들고 상속을 적용했다. 생성자 부분은 기본예제 참고 main.cpp #include "Student.h" #include "Teacher.h" int main() { using namespace std; Student std("Jack Jack"); std.setName("New Jack"); std.getName(); cout
C++ 상속 기본 예제
·
C++/Class
상속 기본 예제 상속의 본질은 일반화이다. 용어 Generalized class : 상속하는 상위 클래스 Derived class : 상속을 받은 하위 클래스 예제 #include using namespace std; class Mother { int i_; public: Mother(const int& i_in = 0) : i_{ i_in } { cout
C++ 상속 (Inheritance)
·
C++/Class
상속 (Inheritance) is-a relationship 기본 예제 상속 Teacher-Student 예제 유도된 클래스들의 생성 순서 유도된 클래스들의 소멸 순서 상속과 패딩 상속과 접근 지정자 함수 오버라이딩 상속받은 멤버의 접근 권한 변경 다중 상속
C++ 의존 관계 (Dependency)
·
C++/Class
의존 관계 (Dependency) Worker 클래스에서 잠깐 사용하는 Timer 클래스 main.cpp #include "Timer.h" #include "Worker.h" int main() { Worker().doSomething(); } /* stdout 4e-07 */ Timer.h #pragma once #include #include using namespace std; class Timer { using clock_t = std::chrono::high_resolution_clock; using second_t = std::chrono::duration; std::chrono::time_point start_time = clock_t::now(); public: void elapsed() ..
C++ 연계, 제휴 관계 (Association)
·
C++/Class
연계, 제휴 관계 (Association) 의사 클래스와 환자 클래스로 비유 #include #include using namespace std; class Doctor; class Patient { string name_; vector doctors_; public: Patient(const string &name_in) : name_{name_in} {} void addDoctor(Doctor* new_doctor) { doctors_.push_back(new_doctor); } void meetDoctors(); friend class Doctor; }; class Doctor { string name_; vector patients_; public: Doctor(const string &name_..
C++ 구성 관계 (Composition Relationship)
·
C++/Class
구성 관계 (Composition Relationship) 몬스터 클래스와 그의 멤버인 좌표 클래스로 비유했다. Monster 클래스의 멤버로 존재하는 Position2D 클래스 인스턴스 location_ (Monster.h 참고) 이 location_ 인스턴스는 Monster 클래스로 만들어진 mon1 인스턴스의 Part-of라고 할 수 있다. mon1이 소멸하면 자동으로 location_도 소멸한다. main.cpp #include "Monster.h" int main() { using namespace std; Monster mon1("Sanson", Position2D(0, 0)); cout
C++ 객체들의 관계 (Object Relationship)
·
C++/Class
객체들의 관계 (Object Relationship) 관계 관계를 표현하는 동사 예시 구성 (Composition) Part-of 두뇌는 육체의 일부이다 집합 (Aggregation) Has-a 어떤 사람이 자동차를 가지고 있다. 연계 (Association) Uses-a 환자는 의사의 치료를 받는다. 의사는 환자들로부터 치료비를 받는다. 의존 (Dependency) Depends-on 나는 목발을 짚었다. 관계 관계의 형태 다른 클래스에도 속할 수 있는가 멤버의 존재를 클래스가 관리하는가 방향성 구성 (Composition) 전체/부품 No Yes 단방향 집합 (Aggregation) 전체/부품 Yes No 단방향 연계 (Association) 용도 외 무관 Yes No 단방향, 양방향 의존 (Depe..