본문 바로가기
  • 쓸쓸한 개발자의 공부방

cpp39

[C++] 디자인 패턴 : 변하는 것을 분리하는 방법 2가지 [C++] 디자인 패턴 : 변하는 것을 분리하는 방법 2가지 클래스를 정의하고 상속 받아서 사용하는 경우 재사용성을 고려하는 디자인 패턴에 대해 알아야 한다. 변하지 않는 코드(전체 흐름) 안에 있는 변해야 하는 부분(정책)은 분리 하는 것이 좋다. 1) template method : 변하는 것을 가상함수로 (상속 기반) 변해야 하는 부분 (아래에서 validate 함수)을 별도의 가상 함수로 분리한다. 변하는 것 (validate)을 가상 함수로 분리할 때의 장점 - validation 정책을 변경하고 싶다면 Edit의 파생 클래스를 만들어서 validate() 가상 함수를 재정의하면 된다. template method 장단점 상속 기반은 유연성이 떨어지는 편, 재사용이 크게 필요없는 경우 명확한 편.. 2022. 1. 30.
[C++] cout, endl 원리, operator<< 재정의 cout 원리 cout 은 ostream 타입의 객체이다. 모든 primitive 타입에 대해서 operator 2022. 1. 2.
[C++] 연산자 재정의 (operator overloading) 연산자 재정의 (operator overloading) 연산자 재정의란 +, -, * 의 연산자를 함수로 만들 수 있다. operator+, operator-, operator* #include class Point { int x; int y; public: Point( int a = 0, int b = 0) : x(a), y(b) {} }; int main() { int n = 1 + 2; Point p1(1,1); Point p2(2,2); Point p3 = p1 + p2; // operator+(p1, p2) // operator+(Point, Point) // p1.operator+(p2) => operator+(Point) ¸âšöÇÔźö } a+b를 컴파일러가 해석하는 방법 a,b 모두 pr.. 2022. 1. 1.
[C++] 다중 상속 (multiple inheritance) 다중 상속 (multiple inheritance) 다중 상속은 클래스가 2개 이상의 기반 클래스로 부터 상속 되는 것이다. - C++, Lisp, Curl 다중 상속 지원 - Java, C# 다중 상속 미지원 문제점 : 서로 다른 기반 클래스에 동일 이름의 멤버가 있을 때 이름 충돌, 다이아몬드 형태의 상속 class InputFile { public: void read() {} void open() {} }; class OutputFile { public: void write(){} void open() {} }; class IOFile : public InputFile, public OutputFile // 다중 상속 지원 { }; int main() { IOFile file; file.open().. 2021. 12. 31.
[C++] 상속과 RTTI 상속과 RTTI 함수가 인자로 기반 클래스의 포인터를 받으면 - 기반 클래스 뿐 아니라 모든 파생 클래스를 전달 받을 수 있다. 기반 클래스 포인터로 파생 클래스의 고유 멤버에 접근 할 수 없다. - 파생클래스의 고유 멤버에 접근하려면 파생 클래스 타입으로 캐스팅 (다운 캐스팅, downcasting) 해야 한다. #include #include class Animal {}; class Dog : public Animal { public: int color; }; void foo(Animal* p) { // p가 Dog 이라면 p->color = 10; // error } int main() { Animal a; foo(&a); Dog d; foo(&d); } 아래와 같이 p는 Animal 클래스 형태로.. 2021. 12. 30.
[C++] RTTI (Run Time Type Information) RTTI(Run Time Type Information) 실행시간에 타입의 정보를 얻을 때 사용하는 기술 헤더 포함하고 typeid 연산자를 사용하면 된다. 타입의 정보를 담은 type_info 객체를 얻을 수 있다. type_info 객체의 멤버 함수 name()을 사용해 출력 가능하다. #include #include int main() { int n1 = 10; auto n2 = n1; // n2의 타입은 int ? const std::type_info& t1 = typeid(n2); std::cout 2021. 12. 29.
[C++] 추상 클래스 (abstract class), 인터페이스(interface) 순수 가상 함수 (pure virtual function) - 함수의 구현부가 없고, 선언부가 =0 으로 끝나는 가상함수 추상 클래스 (abstract class) - 순수 가상 함수가 한 개 이상 있는 클래스 - 객체를 생성할 수 없다. - 포인터 변수는 만들 수 있다. #include using namespace std; class Shape { public: virtual void Draw() = 0; }; int main() { Shape s; // error Shape* p; } 출력 : 추상 클래스의 객체를 생성할 수 없기 때문에 에러가 발생한다. main.cpp:21:11: error: cannot declare variable ‘s’ to be of abstract type ‘Shape’ .. 2021. 12. 28.
[C++] virtual function (가상 함수), function override(오버라이드) 주의! 함수 오버라이드가 c++에서 가능하지만 권장하지 않는 코딩이다. 그저 참조용으로만 알아둘 것. 함수 재정의가 필요한 경우에는 무조건 virtual 을 사용해야 한다. 함수 오버라이드 (function override) - 기반 클래스가 가진 함수를 파생 클래스가 다시 만드는 것 - 주의! 오바라이딩과 오버로딩(overloading)은 다른 용어 #include class Shape { public: void Draw() { std::cout 2021. 8. 28.
[C++] upcasting (업캐스팅) upcasting (업캐스팅) - 기반 클래스 타입의 포인터로 파생 클래스를 가리킬 수 있다. - 기반 클래스 타입의 참조로 파생 클래스를 가리킬 수 있다. class Shape { public: int color; }; class Rect : public Shape { public: int x, y, w, h; }; int main() { Rect rect; Rect* p1 = ▭ // ok int* p2 = ▭ // error. Shape* p3 = ▭ // ok Shape& r = rect; // ok. } main.cpp:18:18: error: cannot convert ‘Rect*’ to ‘int*’ in initialization Shape* p3 = ▭ .. 2021. 8. 27.
[C++] 상속과 생성자 (파생 클래스 구현 방법 및 호출 순서) 상속과 생성자 파생 클래스의 객체 생성시 생성자와 소멸자 호출 순서 1. 기반(base) 클래스 생성자 2. 파생(Derived) 클래스 생성자 3. 파생(Derived) 클래스 소멸자 4. 기반(base) 클래스 소멸자 #include using namespace std; class Base { int data; public: Base() { cout 2021. 8. 26.
[C++] 상속 (Inheritance), protected 상속(INHERITANCE) - 한 클래스가 다른 클래스에서 정의된 속성들 (데이타, 함수) 를 이어 받아서 사용하는 것! - 이미 정의된 클래스를 기반으로 새로운 클래스를 설계 - 소프트웨어 재사용성을 지원 장점 - 코드 중복을 막는다 - 상속을 통해서 기존 클래스에 새로운 특징을 추가한 새로운 타입의 설계 - 다형성을 활용한 객체지향 디자인 기법 상속의 기본 개념 교수님과 학생 클래스가 아래와 같이 있다. 두 클래스는 이름과 나이의 공통 속성이 있다. #include #include class Professor { std::string name; int age; int major; }; class Student { std::string name; int age; int id; }; int main().. 2021. 8. 25.
[C++] this 포인터 this 포인터 - 멤버 함수 안에서 사용가능한 키워드 - 자신을 호출한 객체의 주소를 담고 있다. 객체를 여러 개 생성 할 때 멤버 데이터는 객체당 한 개씩 메모리에 놓이게 된다. 멤버 함수는 객체의 개수에 상관없이 코드 메모리에 한 개만 있다. #include class Point { int x = 0; int y = 0; public: void set(int a, int b) { std::cout x = x; this->y = y; return *this; } }; int main() { Point p1; //p1.set(10,20)->set(30,40)->set(40,50); // 포인터를 반환하면 "->" 사용가능 p1.set(10,20).set(30,40).set(40,50); // cout의.. 2021. 8. 24.
[C++] 상수 멤버 함수 const 상수 멤버 함수 const 함수 선언 및 구현시 함수 괄호 ( ) 뒤에 const가 붙는 함수 void print() const - 상수 멤버 함수 안에서는 모든 멤버를 상수 취급한다. - 멤버 데이터의 값을 읽을 수는 있지만 변경할 수는 없다. - 코드 작성시 안정성 - 상수 객체는 상수 멤버 함수만 호출할 수 있다. #include class Point { int x, y; public: Point(int a = 0, int b = 0) : x(a), y(b) {} void set( int a, int b ) { x = a; y = b; } void print() const // 상수 멤버 함수 { x = 10; // error : 상수 멤버 함수 안에서 모든 멤버를 상수 취급하기 때문에 변경시 에러.. 2021. 8. 23.
[C++] static member (정적 멤버), static 변수, static 함수 static 변수는 실무에서 사용에 매우 제한을 두는 코딩이다. 메모리가 할당되어 계속 자리를 차지 하고 있기 때문이다. 사용 방법을 정확히 파악해 꼭 필요한 경우에만 static 변수를 선언해 사용하자. static member 전역 변수 기본 접근 : 자동차의 총 개수를 파악하기 위한 전역 변수를 아래와 같이 사용이 가능하다. #include int cnt = 0; // 전역 변수 // 자동차의 총 개수를 파악하기 위해 cnt 변수 선언 class Car { int speed; int color; public: //int cnt = 0; // member 로 만들면 각 클래스 마다 각자 정보를 갖고 있음. Car() {++cnt;} ~Car() {--cnt;} }; int main() { Car c1.. 2021. 8. 22.
[C++] 복사 생성자 (copy constructor), 얕은 복사 (Shallow Copy), 깊은 복사 (deep copy) 눈에 잘 드러나지 않는 자동 생성되는 코드를 이해하는 부분이 항상 까다롭다. 그 중 하나가 복사 생성자다. 대부분 자동으로 생성되는 복사 생성자를 사용하게 되고 큰 문제는 없다. (좀더 인텔리전트한 개발자가 되기 위해서) 몇몇 부분에서 성능 향상에 도움이 되는 복사 생성자 정의하는 포인트가 있다. 알아두면 정말 좋은 내용이다. copy constructor ( 복사 생성자 ) - 자신과 동일한 타입 한 개를 인자로 가지는 생성자 - 사용자가 복사 생성자를 만들지 않으면 컴파일러가 자동으로 제공한다. - 디폴트 복사 생성자다 (default copy constructor) - 모든 멤버를 복사 한다. #include class Point { public: int x; int y; Point() : x(0).. 2021. 8. 21.
[C++] Explicit 생성자 Explicit 생성자 explicit a. 명백한, 뚜렷한(clear), 명시적인 - 직접 초기화 (direct initialization) : OFile fi("a.txt");와 같이 '=' 없이 초기화 하는 것 - 복사 초기화 (copy initialization) : OFile f2 = "a.txt"; 와 같이 '=' 사용해서 초기화 하는 것 함수 인자 전달시 복사 초기화를 사용한다. foo("hello")를 보낸다는 것은 hello 이름으로 File이 error 없이 생성이 된다. 특정 클래스 설계시 복사 초기화를 사용하지 못하게 하는 것이 좋을 때가 있다. #include class OFile { FILE* file; public: OFile(const char* filename) { file.. 2021. 8. 20.
[C++] Class : 멤버 초기화 리스트 (member initializer lists) 멤버 초기화 리스트 (member initializer lists) 생성자 괄호 ( ) 뒤에 콜론 (:) 을 표기하고 멤버를 초기화 하는 것 Point( int a, int b) : x(a), y(b) { } 대입 방식이 아닌 초기화 방식이다. 멤버 초기화 리스트를 사용하는 방향이 성능면에서 더 좋다. 클래스 선언부 구현부가 분리되어 있을 때, 초기화 리스트는 구현부에 작성한다. #include class Point { int x; int y; public: Point( int a, int b) : x(a), y(b) // 초기화 { // x = a; // 대입 // y = b; } }; int main() { Point p(1, 2); int a = 0; // 초기화. 생성자 호출 int b; // 생.. 2021. 8. 19.
[C++] 생성자, 소멸자, 위임 생성자, default 생성자 생성자 (constructor)와 소멸자 (destructor) "생성자 (constructor)" 생성자를 사용하는 이유 - 객체를 자동으로 초기화 하기 위해서 생성자 모양 - 클래스 이름과 동일한 함수 - 리턴 타입이 없다. - 인자는 있어도 되고 없어도 된다. 2개 이상 만들 수 있다. 객체를 생성하면 - 객체의 크기 만큼 메모리를 할당 - 생성자가 호출된다 - 생성자가 없으면 객체를 만들 수 없다. 디폴트 생성자 - 사용자가 생성자를 한 개도 만들지 않으면 디폴드 생성자를 컴파일러가 인자없는 생성자를 제공해 준다. #include using namespace std; class Point { int x, y; public: Point() { x = 0; y = 0; cout 2021. 8. 19.
[C++] 객체지향 : 접근지정자 private, public, friend 접근지정자 private / public - 사용자는 내부 멤버 데이터 구조에 대해 굳이 알 필요가 없다. - 멤버 함수를 통해서만 객체 상태 변경이 가능하도록 해서 객체를 안전하게 유지한다. 이를 캡슐화라 말한다. - setter / getter : 멤버 데이터 접근을 위해 함드는 함수를 나타내는 용어, private 멤버 데이타를 선언하고 setter/getter로 접근하는 것이 일반적 자전거의 기어는 현실 세계에서 항상 존재함. 프로그램에서 잘못된 기어 생성을 막아야 한다. gear의 값이 마이너스 값이거나 0 인 경우는 값 셋팅이 되지 않도록 하는 조건을 만들어 넣을 수 있다. #include class Bike { public: void changeGear(int n) { if ( n < 1 ).. 2021. 8. 18.
[C++] STL : stack, vector 다양한 STL 이 있지만 그 중 가장 많이 자주 사용하는 stack과 vector를 살펴 보겠습니다.! STL - stack STL (Standard Template Library) 은 C++에서 제공하는 표준 라이브러리 #include #include // stack 사용을 위해 해당 header추가 해야함. int main() { std::stack s; // 클래스 탬플릿으로 되어 있어 input type을 적어줘야 함. s.push(10); s.push(20); s.push(30); std::cout 2021. 8. 17.