클래스를 만든다는 것은 새로운 타입을 만든다는 것이나 다름이 없다. 그러기에 '잘' 만들어야 한다. 잘 만들기 위해서 다음과 같은 항목이 제대로 내 코드에 적용이 됐는지 확인해 보자 1. 새로 정의한 타입의 객체 생성 및 소멸은 어떻게 이루어져야 하는가? 이 부분이 어떻게 되느냐에 따라 클래스생성자 및 소멸자의 설계가 바뀐다. 그리고 만약 메모리 할당함수를 operator new, operator new[], operator delete, operator delete[])직접 작성한 경우에도 이들 함수 설계에 영향을 끼친다. 2. 객체 초기화는 객체 대입과 어떻게 달라야 하는가? 클래스의 초기화와 대입은 호출되는 함수부터가 다르다. 완전 다른개념이니 잘 구분하자 3. 새로운 타입으로 만든 객체가 값에 의..
1단계는 13인가? 14인가? 까지 갔고 2단계는 9단계까지밖에 못 갔어 9단계 딱 도착했을 때는 1시간 30분이 남아있었는데 거기서 완전 막혀 버린 거 있지? 그래서 멘붕 와버렸어;; 그리고 알바하고 돌아와서 인지 졸리기도 했었고 그래서 30분 남았었나? 거기서 푸는 도중에 잠들어버렸어! 으아.. 근데 잠들지 않았어도 못 풀었을 거 같아 ㅎㅎ;;사람들 보니까 12~15 갔다는 거야 와 진짜 새삼스럽지만 내가 코딩에 재능이 없다는 걸 깨달았어 ㅠㅠ 슬프다. 그래도 노력하면 빛은 보겠지? 만약 7월까지 한번 더 도전해볼까 생각 중이야 흑흑.....
저 밑에 액션 어드벤터 게임에서 사용할 클래스와 인터페이스가 어지럽게 흩어져 있습니다. 게임 캐럭터용 클래스와 캐릭터가 게임에서 사용할 수 있는 무기의 행동에 관한 클래스를 찾을 수 있을 것입니다. 각 캐릭터는 한 번에 한 가지 무기만 사용할 수 있지만 게임도중에 무기를 바꿀 수 있습니다. 여러분은 이제 이 클래스와 인터페이스를 잘 정돈해야합니다. 해야 할 일: 1. 클래스를 정돈한다. 2. 추상 클래스 한 개, 인터페이스 한 개, 그리고 클래스 여덟 개를 골라낸다. 3. 적당한 클래스를 찾아서 setWeapon()(무기설정 메소드)메소드를 집어넣자. #include #include using namespace std; /// /// 무기 /// class WeaponBehavior { private: ..
class CompanyA { public: ; void sendCleartext(const string& msg) {} void sendEncrypted(const string& msg) {} ; }; class CompanyB { public: ; void sendCleartext(const string& msg) {} void sendEncrypted(const string& msg) {} ; }; class ZCompany { public: ; void sendCleartext(const string& msg) {} void sendEncrypted(const string& msg) {} ; }; class MsgInfo {}; template class MsgSender { public: ; v..
C++는 발에 치이고 손에 잡히는것이 인터페이스다. 함수, 클래스, 템플릿 또한 인터페이스 이며 인터페이스는 사용자가 나의 코드와 만리장성을 쌓은 접선수단이다. 그러므로 제목처럼 설계해야한다. 예시를 보자 class Date { public: Date(int month, int day, int year); .....; }; 이렇게 설계를 해 놓으면 month에 넣어햐 할것은 day에 넣거나 year값을 month에 넣거나 실수를 할 수 도있다. 그러므로 다음과 같이 설계를 해 보자 struct Day { int val; Day(int d) : val(d){} }; struct Month { int val; Day(int d) : val(d){} }; struct Year { int val; Year(in..
우리가 비밀번호를 입력받고 입력받은 비밀번호가 너무 짧으면 logic_error예외를 던지도록 하고 그렇지 않으면 비밀번호를 암호화하는함수를 다음과 같이 만들었다고 하자 #include #include using namespace std; enum{MinimumPasswordLength = 8}; string encryptPassword(const string& password) { string encrypted;//B순으로 보겠다. int _tmain() //A방법 { Widget w; for (int i = 0; i < n; i++) w = i; } int _tmain()//B방법 { for(int i=0;i
데이터 멤버는 전부 private로 놔야 한다. 그래야만 문법적 일관성과 캡슐화가 제대로 되기 때문이다. 예를 들어보자 public는 모든 곳에서 접근할 수 있다. 만약 public 멤버 데이터를 누군가가 참조했으면 나중에 고칠 때 그 참조했던 것과 참조한 것을 참조한 것을 모두 고쳐야 한다. 그리고 protected도 마찬가지이다. protected는 상송된 관계 모드가 참조 가능하다 그렇다면 이것도 똑같이 수정 시에 모두 수정하여야 한다. 이제 private에 대해서 말하겠다. 아까 무법의 일관성을 지키려면 private를 사용하라고 한 것 기억하는가? 난 이게 확 와 닿지 않았다. 하지만 정교한 제어가 가능하다고 하니까 그때서야 느낌이 "파밧!" 왔다. 는 구라고 소스코드 보고 아 "그런갑다~" 했..
지금 가지 배운 것들 한번 적용해 보려고 만들어봤는데 너무 작아서 배운 것 전부다 적용은 못했어 그래도 거기에 해당하는 것들은 하나하나 되짚어보면서 해봤는데 ㅎㅎ;; 잘 모르겠네! 2021-02-26 그래서 카톡에서 코드 리뷰를 받았어 너무 고마우신 분인 거 같아 어떻게 진단을 받았냐~ 하면은 아파... 너무 많이 맞았어 ㅠㅠ 그래도 진단해주셨으니 너무 감사하지 이렇게 해주시는 분 별로 없을 텐데 말이야 그리고 Hide님도 도와주셨어 매우 많은 숙제를 내주셨지(아 ㅋㅋ) 그래서 바꾼 게 이거야! 모르는 것도 알려주시고 7번 마지막에 또 숙제가 있더라고 그래서 일하면서 간간히 해보려고 이제 이것까지만 해보고 이펙티브도 더 읽고 여러가지도 알아보고 리팩토링도 해봐야지. 1. MVC패턴에 대해서 알아보고(다른..
데이터클래스와 데이터 관리 클래스 그리고 데이터 관리 클래스와 데이터 클래스 사이에 있는 관리 시스템 은행과 비유하면 딱 이런거 같아(아마도 ㅇㅇ) 그리고 지금 까지 한 effective c++ 항목들 18개 이 프로그램 적용시켜봐야지. Chapter 1 C++에 왔으면 C++의 법을 따릅시다. 항목 1 : C++를 언어들의 연합체로 바라보는 안목은 필수! 항목 2 : #define을 쓰려거든 const, enum, inline을 떠올리자 매크로 함수대신 inline함수 쓰고 static const나 enum으로 상수쓰기 항목 3 : 낌새만 보이면 const를 들이대 보자! const그냥 왠만하면 다 걸어버리자 포이터에도 걸고 함수에도 걸고 그리고 코드중복을 제거하자 항목 4 : 객체를 사용하기 전에 반..
잠시 포스팅 중단할게 effective c++을 3장까지 읽었는데 거의 대부분의 항목들을 아슬아슬하게 이해하는 수준밖에 안돼서 4장으로 가기 전에 다시 되짚어 보려고 해. 그래서 그동안은 effective c++ 카테고리에선 포스팅 중단할게 그리고 영어 공부도 조금씩 해야할거같아 정말로.. 초등학교 3학년 때부터 영어 놔서 진짜 하나도 모르거든 근데 여기서는 영어가 거의 필수라고 하더라고 어쩔 수 있겠어~ 돈 벌라면 해야지 머리가 좋았으면 좋겠똬!
Widget이라는 클래스가 있고 우선순위를 반환하는 priority() 라는 함수와 shared_ptr객체와 우선순위를 매개변수로 받는 processWidget()함수가 있다고 하자(아래 코드를 보자) class Widget { public: }; int priority(){return 1;}; void processWidget(shared_ptr pw,int priority) { cout
밑의 코드를 보고 잘못된 점을 찾아보자 int _tmain(int argc, char** argv) { string *stringArray = new string[100]; delete stringArray; } 잘못된점이 보이는가? delete를 보면 잘못된 점을 찾을 수 있다. new 로 배열을 하당했는데 delete[]가 아닌 delete이다. 이렇게 되면 문제가 무엇이냐 하면 delete가 할당한 데이터가 배열인지 아닌지 자동으로 확인하지 못한다는 것이다. 100개의 배열을 할당했는데 delete를 사용하면 나머지 99개는 붕~ 뜨는것이다. 그러므로 "나는 배열을 할당해제할 것이다~" 라는 것을 알리기위해 delete 앞에 []를 써주는것이다. 여기서 궁금한점! "delete[]은 배열의 크기를 ..
우리가 shared_ptr로 객체를 만들고 그 객체 안에 있는 포인터를 매개변수로 넣어 주려고 한적 있을 것이다. 근데 그건 안된다. 암시적인 형변환이 안되기 때문에 get() 함수를 써야지 인자를 제대로 넘겨줄 수 있다. class TEST1 { private: int i; public: TEST1():i(7777) {} TEST1(const TEST1& rhs) {} void TestFunc(const TEST1* const rhs) const { cout i TestFunc(t1);//error t1->TestFunc(t1.get());//이건 정상작동 //t1에 들어있는 실제 포인터를TestFunc에 넘김 } 왜냐하면 코드상의 t1은 shared_ptr"클래스"로 만들어진 것이다 그러기 때문에 형..
우릭가 복사 생성자와 복사 대입연산자를 직접 선언하지 않으면 컴파일러가 자동으로 만든다는 것 기억하는가? 컴파일러가 자동으로 만들어주는 복사 생성자와 복사 대입연산자는 객체의 모든 부분을 빠짐없이 복사해준다. 하지만 우리가 자동으로 만들어 주는것이 맘에 들지 않아 직접만들면 우리가 하나하나 다 복ㄱ사를 해 주어야한다. 만약 객체 안에 데이터가 추가된다면 복사 생성자, 복사 대입연산자에서 복사해주는 코드를 추가해줘야한다. 하지만 한가지 문제점이 있다. 만약 우리가 파생 클래스를 복사한다고 했을 때 파생 클래스만 복사학다면 그것은 완전한 복사가 아닌 부분 복사나 마찬가지이다. 하지만 쉽게 기본 클래스까지 복사하는 방법이 있다. 코드를 보자 class TEST1 { private: int nData; publ..
예외 안전성을 확보하는 작업은 매우 힘들다. 다음 예쁜 배경 그림을 깔고 나오는 GUI 메뉴를 구현하기 위해 클래스를 하나 만든다고 가정하겠다(병행성 제어를 위해 Mutex사용) class Image { public: Image(const istream& imgSrc) {} }; class PrettyMenu { private: Mutex mutex;//이 객체 하나를 위한 뮤텍스 Image* bgImage;//현재의 배경 그림 int imageChanges;//배경 그림이 바뀐 횟수 public: ...; void ChangeBackground(const istream& imgSrc);//배경 그림을 //바꾸는 멤버 함수 ...; }; void PrettyMenu::ChangeBackground(con..
세상의 모든 자원은 힙에서만 생기지 않는다. 그리고 힙에서 생기지 않은 자원은 스마트포인터로 처리하지 않는 게 일반적인 견해이다. 항상 그런 것만은 아니지만 우리가 직접 자원관리 클래스를 만들어야 할 때가 있다. 예시를 봐보자 뮤텍스 잠금을 관리하는 클래스를 하나 만들고 싶은데 이전에 걸어놓은 뮤텍스를 잊지 않고 풀어주기 위해서 이 코드를작성했다고치자 class Lock { public: explicit Lock(Mutex* pm) : mutexPtr(pm) { lock(mutexPtr);//자원을 획득한다. } ~Lock() { unlock(mutexPtr); }//자원을 해제한다. void lock(Mutex* pm) {} void unlock(Mutex* pm) {} private: Mutex* m..
자기 대입이란 (self assignment) 어떤 객체가 자기 자신에 대해 대입 연산자를 적용하는 것을 말한다. 아래의 코드처럼말이다. class Widget{...}; Widget w; ... w = w;//자기에 대한 대입 이 때 조심해야 하는것이 있다. 밑의 코드를 봐보자 class Bitmap { ... }; class Widget{ private: Bitmap* pb;//힙에 할당할 객체를 가르키는 포인터 public: ... }; Widget& Widget::operator=(const Widget& rhs) //안전하지 않게 구현된 operator= { delete pb;//현재의 비트맵 사용을 중지한다. pb = new Bitmap(*rhs.pb);//이제 rhs의 비트맵을 //사용하도록..
Widget& operator = (const Widget& rhs) Widget& operator += (const Widget& rhs) Widget& operator-= (const Widget& rhs) Widget& operator*= (const Widget& rhs) Widget& operator/= (const Widget& rhs) Widget7 oeprator=(int rhs) 뭐 이런것들 등등 전부다 반환을 *this로 해주자 관례라고 하니까 따라야지 이것만은 잊지 말자! 1. 대입 연산자는 *this의 참조자를 반환하도록 만들어라
밑의 코드를 봐보자 class Transaction//모든 거래에 대한 {//기본 클래스 public: Transaction(); virtual void logTransaction() const = 0;//타입에 따라 달라지는 //로그 기록을 만든다. ....; }; Transaction::Transaction()//기본 클래스 생성자의 구현 { ...; logTransaction();//마지막 동작으로, 이 거래를 }//로깅을 구현한다. class BuyTransaction : public Transaction//Transaction 파생 클래스 { public: virtual void logTransaction() const;//이 타입에 따른 거래내역 ....;//로깅을 구현한다. }; class ..
아래 코드를 보자 class Widget { public: ...; ~Widget() { ...; }//이 함수로부터 예외가 발생된다고 가정하자 }; void doSomething() { std::vector v; }//v는 여기서 자동으로 소멸한다. 위의 코드에서 Widget형인 vector가 10개가 있다고 치자 그런데 첫 번째 Widget을 제거하려는데 소멸자에서 예외가 터져버렸다. 근데 아직 9개나 남아있으므로 다음 것을 또 제거하려 했는데 또 소멸자에서 예외가 터져버렸다. 어떠한 조건에 의해 예외가 동시에 터져서 C++ 이 감당하기 어려워진다면 프로그램이 꺼진다거나 오작동을 보일 것이다. 다른 예시를 보자 class DBConnection { public: ... static DBConnecti..
본가에서 아버지가 냉이된장국인가? 그거 기똥차게 끓여서 많이는 안 먹고 적당히 먹고 잠시 뭐 심어야 해서 삽질 2시간 정도 도와줬는데 갑자기 멀미 난 것처럼 어질 하고 속이 안 좋아져서 4시간인가 5시간 동안 누워버렸네. 아직 20대 중반인데 너무 몸이 허약하넹;; 예전에는 이렇게 까지는 아니었는데 근데 예전엔 안 그랬는데 요즘은 밥 먹으면 더부룩하고 위에 가스가 찬 거 같고 방귀도 너무 많이 나오는 거 같아 ㅋㅋ 그리고 매번은 아니지만 속도 쓰리고 ㅇㅇ;; 이번에 한번 건강검진받아봐야겠다. 뭔가 쓸 때 없이 무섭네 쫄보라서 그런가 ㅋㅋ