'C,C++ /Android_FrameWork'에 해당되는 글 35건

  1. 2012.08.17 [SSM 안드로이드 프레임워크 개발 강의]32. 클라이언트에서 바인더로 통신방법의 원리
  2. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]31. 퍼팩트 포워딩
  3. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]30.Traits (타입 판독 STL)
  4. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]29. 템플릿이야기3 (멤버함수 템플릿)
  5. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]28. 템플릿이야기 2(클래스 템플릿)
  6. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]27. 템플릿이야기 1
  7. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]26. RTTI , RTCI 직접 구현해보기
  8. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]25. RTTI 이야기
  9. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]24. 가상 소멸자 이야기
  10. 2012.08.16 [SSM 안드로이드 프레임워크 개발 강의]23. 가상함수의 원리와 함수포인터이해
  11. 2012.08.15 [SSM 안드로이드 프레임워크 개발 강의]22. 범용적 함수 포인터와 bind
  12. 2012.08.15 [SSM 안드로이드 프레임워크 개발 강의]21. 인터페이스와 인터페이스 탄생 배경
  13. 2012.08.15 [SSM 안드로이드 프레임워크 개발 강의]20. 접근변경자와 어뎁터 패턴
  14. 2012.08.15 [SSM 안드로이드 프레임워크 개발 강의]19. 메모리 릭을 체크하는 헤더만들기(operator New , Delete)
  15. 2012.08.15 [SSM 안드로이드 프레임워크 개발 강의]18. New 연산자 이야기
  16. 2012.08.14 [SSM 안드로이드 프레임워크 개발 강의]17. 변환 연산자와 변환 생성자. 그리고 활용.
  17. 2012.08.14 [SSM 안드로이드 프레임워크 개발 강의]16. STL 과 함수객체
  18. 2012.08.14 [SSM 안드로이드 프레임워크 개발 강의]15. STL find, strchr 구현하기
  19. 2012.08.14 [SSM 안드로이드 프레임워크 개발 강의]14-3.실제로 안드로이드 프레임웤에서 사용되는 스마트 포인터
  20. 2012.08.14 [SSM 안드로이드 프레임워크 개발강의]14-2 스마트포인터의 얕은복사 해결과 템플릿
  21. 2012.08.14 [SSM 안드로이드 프레임워크 개발 강의]14-1.스마트 포인터
  22. 2012.08.14 [SSM 안드로이드 프레임워크 개발 강의]13.연산자 재정의와 테크닉
  23. 2012.08.14 [SSM 안드로이드 프레임워크 개발 강의]12-1 얕은 복사의 4가지 기법
  24. 2012.08.14 [SSM 안드로이드 프레임워크 개발 강의]12. 복사생성자
  25. 2012.08.13 [SSM 안드로이드 프레임워크 개발 강의]11. 함수포인터로 구현해본 안드로이드 Thread 예제제
  26. 2012.08.13 [SSM 안드로이드 프레임워크 개발 강의]10. 멤버함수 호출의 정리
  27. 2012.08.13 [SSM 안드로이드 프레임워크 개발 강의]9.템플릿으로 알아보는 싱글톤 패턴
  28. 2012.08.13 [SSM 안드로이드 프레임워크 개발 강의]8. 상수함수 이야기
  29. 2012.08.13 [SSM 안드로이드 프레임워크 개발 강의]7. 생성자 이야기
  30. 2012.08.13 [SSM 안드로이드 프레임워크 개발 강의]6. 객체 지향의 탄생 배경을 STACK 소스로 알아보기
2012.08.17 10:53


ILedService.h


서버1.cpp


서버2.cpp


클라이언트1.cpp


클라이언트2.cpp


클라이언트3.cpp


위파일들은 헤더를 기준으로 서버1 -> 에서 좀더 객체지향적인 서버 2가 완성되었고

클라이언트도 1-> 2 -> 3 순서로 수정되어 같은 역할을 하는 것을 좀더 OCL 에 맞추어 개발하는 방향이다.

완성코드는 아래와 같다.


========================================== [ Server ]=================================================


#include<Windows.h>

#include<iostream>

#include<conio.h>


using namespace std;

void binder_loop(void (*handler)(int,int ,int))

{


//여기서 바인더 드라이버를 Open 해서 Client 에서 오는 event를 대기합니다.

//우리는 윈도우 메세지로 흉내 내도록 하겟습니다.

while(1)

{

MSG msg;

GetMessage(&msg,0,0,0);

handler(msg.message,msg.wParam,msg.lParam);


}

}


//---------------------------------------------------------

void Ontransact(int code, int param1, int param2)

{

switch(code)

{

case 5: cout << "LED ON" <<endl; break;

case 6: cout << "LED OFF" << endl; break;

}

}


DWORD __stdcall ServerMain(void *)

{

cout << "서버시작"<< endl;

binder_loop(Ontransact);

return 0;


}

================================== [ Client ] ===================================================

#include<Windows.h>

#include<iostream>

#include<conio.h>

#include "ILedService.h"


using namespace std;


DWORD ServerID=0;


DWORD __stdcall ServerMain(void *);

//---------------------------------------------------------------

//안드로이드가 제공해주느 함수 부분

void binder_call(int code, int param1, int param2)

{


PostThreadMessage(ServerID,code,param1,param2);


}


class IBinder

{

public:

void transact(int code, int param1, int param2){

binder_call(code,param1, param2);


}

};

//서비스 이름을 인자로 받아서 해당 서비스와 통신하기 위한 바인더를 만들어주는 

//함수


IBinder * getService(char *name )

{

//드라이버를 오픈해서 통신할 수 있는 바인더를 만들어 리턴

return new IBinder;

}

class BpRefBase

{

private :

IBinder *mRemote;

public :


BpRefBase(IBinder *p) : mRemote(p) {}

IBinder * remote() { return mRemote;}


};

//proxy 제작시 - 다중 상속을 단일 상속화 한다.

template<typename INTERFACE>

class BpInterface : public INTERFACE ,public BpRefBase

{

public :

BpInterface(IBinder *p) : BpRefBase(p){} //주의!

};


template<typename INTERFACE> INTERFACE * interface_cast(IBinder *p){

return INTERFACE::asInterface(p);


}


//--------------------안드로이드 제공소스 끝 ---------------------------------

// 이제 바인더를 바로 사용하지 말고 함수 호출처럼 변경하는 클래스를 제공합니다

//

//Proxy : 함수 호출 -> RPC 코드 변경 하는 역할.

//

class BpLedService : public BpInterface<ILedService>

{

public :


BpLedService(IBinder * p) : BpInterface<ILedService>(p){}


//////////////////////////////////////////////////////////

// void LedOn(){remote()->transact(5,0,0);}

// void LedOff(){remote()->transact(6,0,0);}

// 위의 경우는 어느게 ledOn인자 LedOFF인지 숫자를 외워야한다...

// 때문에 pLed를 만든다

//////////////////////////////////////////////////////////

void LedOn(){remote()->transact(5,0,0);}

void LedOff(){remote()->transact(6,0,0);}

};


//이제 proxy 제작자는 proxy 클래스를 제공한후 반드시 asInterface 구현부를 

// 제공하기로 약속 한다.

//

ILedService * ILedService ::asInterface(IBinder *svc){

return new BpLedService(svc);

}

void ClientMain(){


IBinder * svc = getService("LedService");

//이제 바인더를 바로 사용하지 말고 __ 로 변경해서 사용합니다.

//BpLedService *pLed = new BpLedService(svc); //강한 결합

//ILedService * pLed = ILedService::asInterface(svc);//약한 결합


ILedService * pLed = interface_cast<ILedService>(svc); // 약한결합을 간지나게 바꿈 

//바인더를받아 스테틱 캐스팅느낌으로...(사실은 프락시)



while(1)

{

// getch(); svc->transact(5,0,0);

// getch(); svc->transact(6,0,0);

getch(); pLed->LedOn();

getch(); pLed->LedOff();

}


}


int main()

{

CreateThread(0,0,ServerMain,0,0,&ServerID);

Sleep(1000);

ClientMain();

getch();

}




Posted by k1rha
2012.08.16 17:46

#include<iostream>


using namespace std;



///////////////////////////////////////////////////////////////////

// perfect forwarding (완벽한 전달자 문제)

////////////////////////////////////////////////////////////////////


void foo(int &a){

a+=10;

cout << "foo" << endl;

}

void goo(int a){cout << "GOO " << endl;}



//함수를 호출해주는 도구 - 바인더가 결국 함수를 가지고 있다고 다시 호출해

// 주는 것입니다.

//

template<typename F, typename ARG> void Caller(F f,const ARG &a)  //함수도 전달되고 상수도 전달되는 퍼팩트 포워딩법

{


f(a);

}


int main(){

//goo(10);

Caller(goo,10);

}


/*

int main(){

int a= 10;

//foo(a);

Caller(foo,a);

cout << a <<endl;

}


*/








Posted by k1rha
2012.08.16 14:57

#include<iostream>


using namespace std;


///////////////////////////////////////////////////////////////////////////////////////////////////////////

// traits 이야기

// 1.Traints : T의 특질(특성)을 조사하는 기술 ...(template 에서 특성에 따라 받아들임이 다름을 이용하는 기술

// primary template 에서 false 를 리턴 (enum 상수가 false)

//

//////////////////////////////////////////////////////////////////////////////////////////////////////////

//


template<typename T> struct my_is_array

{

enum {size=-1}; 

enum {value = false};

};

template<typename T,int N> struct my_is_array<T [N]>

{

enum {size =N};

enum {value =true};

};

template<typename T> void foo(const T& a)

{

if(my_is_array<T>::value)

cout<<"배열 입니다" << my_is_array<T>::size <<endl;

else

cout<<"배열이 아닙니다" << endl;


}

/*

template<typename T>struct my_is_pointer

{

enum{ value = false};

};

template<typename T>struct my_is_pointer<T*>

{

enum{ value = true};

};


template<typename T>void foo(const T& a)

{

if(my_is_pointer<T>::value)

cout<< "T는 포인터 입니다"<<endl;

else

cout<<"T는 포인터가 아닙니다." << endl;


}


*/

/*

template<typename T> T Max(T a, T b)

{

//return 은 주소 비교를 할수 없기때문에.. 좀더 if 문을 넣어 똑똑하게 만들자

if(T is Pointer)

return *a < *b ? b : a;

return a< b ? b : a;


}

*/


int main()

{

//int x = 10, y = 20;

/*

Max(x,y);

Max(&x, &y);

*/


int x = 0;

int y[19];

foo(x);

foo(y);


}

Posted by k1rha
2012.08.16 11:47

#include<iostream>

using namespace std;


///////////////////////////////////////////////////////////////////////////////////////

// 클래스 템플릿의 멤버 함수 템플릿이 사용되는 대표적인 경우

// 1. complex 를 템플릿으로 설계하는 이유 

// 2. T a = T(); => zero initialize : T 가 포인터 또는 빌트인 타입이면 0

// User 타입이면 디폴트 생성자로 초기화

//

//

////////////////////////////////////////////////////////////////////////////////////////


template<typename T>class complex{


T real;

T image;


public:

complex(int a =T() , int b=T()) : real(a), image(b){}

//  Template 복사 생성자!!

// "U 가 T로 복사 될수 있을때 complex<U> 는 complex<T>로 복사 될 수 있어야 한다.

///

template<typename U>complex(const complex<U> & c) : real(c.real), image(c.image)

{


}

template<typename > friend class complex;

};


int main(){

// so <Dog> p1 = new Dog;

// sp <Animal> p2 = p1;  //template 복사 생성자가 있어야 한다.

//  



complex<int> c1(1 , 2);

complex<int> c2 = c1; //복사 생성자!! 

complex<double> c3= c1;



}

Posted by k1rha
2012.08.16 11:45

#include<iostream>


using namespace std;


// 1. stack Vs stack<T>

//


template <typename T> class Stack

{


public : 

// 다음중 생성자로 맞는것은?

Stack() {} //1

Stack() { } //2


//다음중 복사 생성자로 맞는 것은? 


Stack(const Stack &s){} //1  클래스 안에서는 이 표현도 허용된다.

Stack(const Stack<T>& s){} // 2 OK 정확한 표현?! 


//멤버 함수의 외부 구현

void push(const T& a);

//클래스 템플릿의 멤버 변수  함수 템플릿


template<typename U> T foo(U a);

};

template<typename T >void Stack<T>::push(const T& a){

}


template <typename T> template<typename U> stack<T>::foo (U a){}


int main(){


//Stack s1;  //error Stack 은 타입이 아니라 template 이다.

Stack<int> s2;  // OK stack<int> 는 타입이다.


}

Posted by k1rha
2012.08.16 11:44

#include<iostream>

using namespace std;

///////////////////////////////////////////////////////////////////////////////////////

//함수 템플릿 이야기

// 함수 인자 값으로 받으면 : 배열 -> 포인터  함수-> 함수 포인터로 변경하여 전달된다. 

// 이러한 현상을 Decay 라고 부른다.

///////////////////////////////////////////////////////////////////////////////////////


/*

template<typename T>void foo(T a){

//template<typename T>void foo(T& a){ //참조로 받으면 정확한 타입이 넘어온다

//참조냐? 값이냐에 따라 달라진다.


//template 에서는 가상함수가 없어도 빌트인 타입이 없어도 typeid()사용이 가능합니다.

cout << typeid(a).name() << endl;


}


int main(){

int n =10;

int x[10];


foo(n); // T-> int

foo(x);  // int *

foo("apple"); // const char *

foo(main); //int (*)()


}

*/



template<typename T> void foo(const T& a, const T& b)

//template<typename T> void foo(const T a, const T b)

{


}


///아래와 같이 따로 받는것이 나을수도 있따.

void foo(const char *s1, const char * s2)

{

}


int main()

{

foo("orange","apple"); // 함수 찾는 순서

//1. 정확한 타입이 있으면 찾는다

//2. 변환 가능 타입이 있으면 찾는다.

//3. template 버전을 사용한다.


}



Posted by k1rha
2012.08.16 10:55

#include<iostream>


using namespace std;

///////////////////////////////////////////////////////////////////////////////////////

//RTTI 를 직접 구현해보자.

//결국 type_info 는 클래스당 1개의 static 멤버 data 이다.

//type_info 역할의 클래스를 설계하자.

////////////////////////////////////////////////////////////////////////////////////////


struct CRuntimeClass

{

string name; //클래스 이름을 관리


};


// 이제 아래처럼 약속하자! (RTTI 를 직접 구현해보자!!) 

//1.  모든 클래스에는 CRuntimeClass 가 정적 멤버로 있어야 한다.

//2.  이름은 "class클래스 이름 " 으로 약속하자.

//3.  정적 멤버를 리턴하는 가상함수 GetRuntimeClass()를 만들기로 하자.

//


class CObject 

{

public:

static CRuntimeClass classCObject;

virtual CRuntimeClass * GetRuntimeClass() { return &classCObject;}


};

CRuntimeClass CObject::classCObject = {"CObject"};


class CWnd : public CObject{


public :

static CRuntimeClass classCWnd;

virtual CRuntimeClass * GetRuntimeClass() { return &classCWnd;}


};


///////////////////////////////////////////////////////////////

// 여기부분에서 virtual 이므로 재정의 하게 된다

// CObject 타입에 CWnd 를 넣으면 vitual table 의 포인터를 동적으로 참조하므로

// CWnd 함수로 된 것이 호출된다. 이로써 CObject 를 오버라이딩한듯한 효과를 이룬다.

//////////////////////////////////////////////////////////////

CRuntimeClass CWnd::classCWnd = {"CWnd"};


void foo(CObject *p){

// p 가 CWnd 인지 조사해보세요

//

if(p->GetRuntimeClass()== &CWnd::classCWnd )

{

cout << " p 는 CWnd 입니다 " <<endl;

}

}

int main(){


CWnd w; 

foo(&w);

}



////////////////////////////////////////////////////////////////////////////////


Posted by k1rha
2012.08.16 10:54

#include<iostream>


using namespace std;


//////////////////////////////////////////////////////////////////////

// RTTI 이야기

// 1. 가상함수 테이블로 관리되는 type_info 를 얻어서 조사한다.

// 2. typeid(*p) == typeid(Dog) 로 조사한다.

// 3. Dog *p1 = dynamic_cast<Dog *>(p); C# Dog p1 = p as Dog;

//

//

/////////////////////////////////////////////////////////////////////

/*

class Animal{


public:

virtual ~Animal(){}

};


class Dog : public Animal

{


};


void foo(Animal *p) // 모든 동물이 전달 될 수 있다.

{

//ㄹ/결국 아래 코드 표현을 사용하면됩니다.

if(typeid(*p) == typeid(Dog)){

}



 //모든 동물에 공통된 일을 하겠습니다.

 // 그런데 혹시 P가 Dog 라면 다른 일도 하고싶다!

 //P가 Dog 인지 알고싶다 - Run Time Type Information : RTTI 

 //

 //가상 함수 테이블로 관리되는 type_info를 얻어낸다.

const type_info& t1 = typeid(*p);  //typeid (객체)

const type_info &t2 = typeid(Dog); //typeid(클래스 이름)

cout  << t1.name() << endl;


if(t1==t2){

cout << " p는 Dog 입니다."<<endl;


}

cout << t1.name()<<endl;


}


int main(){


Animal a; foo(&a);

Dog d; foo(&d);


}

*/




class Animal{


public:

virtual ~Animal(){}

};


class Dog : public Animal

{


};

void foo(Animal *p){

//Dog *p1 = static_cast <Dog *> (p); //Down cast (부모를 자식포인터로 캐스팅) 을 조사못한다.


//Dog *p1 = dynamic_cast<Dog *>(p); //Down cast 발생시 0이 된다.



cout << p1 << endl;

}

int main(){

Animal a; foo(&a);

Dog b; foo(&d);

}


Posted by k1rha
2012.08.16 09:58

#include<iostream>


using namespace std;;



///////////////////////////////////////////////////////////////

// 가상 소멸자 이야기

// 1. 결론 : 모든 부모의 소멸자는 반드시 가상이어야 한다.

// 어제배운 모든 인터페이스(Ivalidator 등) dp qksemtl rktkd thaufwkfmf cnrkgodigksek.

// 

//////////////////////////////////////////////////////////////

/*

//1.

class Base{

//아래와 같은 문제를 해결하기 위해서 소멸자를 넣어야한다.

//virtual ~Base(){}

};


class Derived : public Base{


public:

Derived() { cout<< " 메모리 할당 " << endl;}

~Derived() {cout << "메모리 해지 " << endl;}


};


int main(){


Base *p = new Derived;

delete p;  //type 이 Base 이기 떄문에 소멸자가 가상함수가 아니라면 P의  타입만 가지고 소멸자 호출.

// 결정한다. static binding.



}

*/


//실행해보세요



/*

//12.

class Base{

//아래와 같은 문제를 해결하기 위해서 소멸자를 넣어야한다.

//virtual ~Base(){}

protected:

~Base{} // 가상 소멸자의 오버헤드를 없애는 기술

//부모 타입으로는 절대 delete 하지말라는 철학.


};


class Derived : public Base{


public:

Derived() { cout<< " 메모리 할당 " << endl;}

~Derived() {cout << "메모리 해지 " << endl;}


};


int main(){


Base *p = new Derived;

delete p;  //type 이 Base 이기 떄문에 소멸자가 가상함수가 아니라면 P의  타입만 가지고 소멸자 호출.

// 결정한다. static binding.


delete static_cast<Derived *>(p);


}

*/


Posted by k1rha
2012.08.16 09:56

#include <iostream>

using namespace std;

/*

class Base

{

int a;


public: inline virtual void foo(){}

virtual void goo(){}

virtual void hoo(){}


};


class Derived : public Base{

int b;

public : 

virtual void foo(){}

};

int main(){


Base b; cout << sizeof(b)<<endl;

Derived d; cout << sizeof(d)<<endl;  

//////////////////////////////////////////////////////////

/// 가상함수 테이블로 인해 4바이트가 늘어난다.

///////////////////////////////////////////////////////////


Base *p = &d;

p->foo();  //*p 가 가르키는 곳을 따라가면 .. goo가 있을 것이다.. 그중에 첫번째 를 호출해 달라.. *p[1]()

//가상 함수의 장점 : 실행 시간 다형성을 얻을 수 있다.

// 단점  : (1) 가상함수 테이블 때문에 메모리 부담. MFC가 이 부담을 없애기 위해 메세지 맵 도입

// (2) 실제 객체의 크기보다 4바이트 더 필요하다. - 약간의 메모리 부담

// (3) 함수 호출시 간접 호출에 따른 속도의 부담

// (4) 인라인 치환이 불가능해서 성능의 부담..

//

// 



}*/

////////////////////////////////////////////////////////////////////////////////


#include<iostream>

using namespace std;


/////////////////////////////////////////////////////////

// 가상함수 이야기 2 

// 가상함수는 실행시간에 어느 함수인지가 결정된다.

// 디폴트 인자는 : 컴파일러가 한다.

// 가상함수에서는 되도록이면 디폴트 인자를 사용하지 말자!.

//

//////////////////////////////////////////////////////////

/*

class A{

int x;

public :

virtual void foo(){ cout << "1" << endl;}

};


class B{

int y;

public:

virtual void goo(){ cout<< "2"<<endl;}

};


int main(){


A a;

B* p = reinterpret_cast<B*>(&a); 

p->goo();


//////////////////////////////////////////////////////////////

//A와 B에 virtual 을 넣었을때와 뺏을떄의 결과값이 다르다.. 왜?!

// 가상함수는 포인터의 개념이기 떄문에, 

// 가상함수가 없을떄는 static binding 을 통해 메모리가 정해지지만

// 가상함수를 넣어줌으로써 dynamic binding 을 통해 상대적으로 가르치고 있는곳을 가르킨다.

////////////////////////////////////////////////////////////////////


}*/

/*

class A{

public :

virtual void foo(int a=10){cout << "1: "<< a<<endl;}

};

class B : public A{  // 이번엔 상속을 봐보자.

public :

virtual void foo(int a=20){cout << "2: "<< a<< endl;}

};

int main(){


A *p = new B;

p->foo(); //실행하지 말고 결과 예측?!

//2 : 10  이나온다..ㅠㅠ 

//컴파일시에는 a가 초기화 되고 , 실행시는 함수포인터가 결정된다

//즉 결과는 *p[1](10) 이 나온다.

}

*/

//////////////////////////////////////////////////////////////////////////////////////////////////

Posted by k1rha
2012.08.15 17:54

#include<iostream>

#include<functional>

using namespace std;

using namespace std::placeholders;



//Dialog 복사해오세요


void foo(int a) { cout << "foo" << a<< endl;}

void goo(int a, int b, int c){ cout<<"goo"<< a<<b<<c <<endl;}


//범용적 함수 포인터 - function

//

class Dialog{

public : 

void Close(){cout<<"Dialog.. Close"<<endl;}

};

int main(){



function<void(int)> f = &foo;

f(1);

//f = &goo; //3개의 이자값을 1개로 대입할수 없다

f = bind(&goo,1,_1,9);

f(3);


function<void()> f2 = bind(&foo,5);

f2();


Dialog dlg;

f2=bind(&Dialog::Close,&dlg);

f2();


}


Posted by k1rha
2012.08.15 15:56

#include<iostream>

using namespace std;


////////////////////////////////////////////////////////////////////////////////////////

// 추상클래 스이야기

// 순수 가상함수가 1개 이상인 클래스

// 강제로 자식에서 특정 함수를 만들라고 지시하는 것!!! 

//

//

////////////////////////////////////////////////////////////////////////////////////////




class Shape{


public : 

virtual void Draw() = 0; //순수 가상함수  구현이 없다.

};

class Rect : public Shape  //Draw()의 구현을 제공하지 않았으므로 추상 클래스 이다.

{


};

int main(){

Shape s; //구현부가 없으므로 에러가 뜬다 // 추상클래스는 객체를 만들 수 없다.

Rect r;  // 에러가 뜬다 사용하고 싶다면 draw()를 만들어야 한다!

}


=========================================================================================

인터페이스의 탄생배경

========================================================================================

#include<iostream>

using namespace std;


// 강한결합 (tightly coupling) : 하나의 클래스 다른 클래스의 이름을 직접 사용 하는것...

// //교체 불가능 경직된 디자인

//스마트폰 제조사와 사람사이ㅔ서의 계약서 (규칙, 인터페이스)를 만들자!

// 모든 스마트폰은 아래 클래스의 자식으로 만들어야 한다.

//

// 약한 결함 (loosly coupling) : 하나의 클래스가 다른 클래스를 사용할떄  부모인 추상클래스를 사용하는 

// //접근법! 교체가능한 설계, 유연한 디자인의 핵심!! 


#define interface struct 

interface ISmartPhone{

public : 

virtual void Calling(char *no) = 0;

//더욱이 인터페이스는 한가지 일만하는게 좋다. 모든 스마트폰의 엠피3기능이 있는것은 아니므로 여러개의 interface를 구현하는게 맞다.

}

interface Mp3function{

public : 

virtual void music(char *no) = 0;

//더욱이 인터페이스는 한가지 일만하는게 좋다. 모든 스마트폰의 엠피3기능이 있는것은 아니므로 여러개의 interface를 구현하는게 맞다.

}



//규칙이 있으므로 진짜 스마트폰이 없어도 사용하는 코드를 먼저 만들 수 있다.

//규칙대로만 사용하면 된다!! 

//


class People{


public :

void UsePhone( ISmartPhone * p ) { p->Calling("010-111-2222");}


};


//이제 모든 스마트폰은 ISmartPhone의 자식이라는 규칙만 지키면된다.




//상송이란 개념을 물려받는 개념... 

//때문에  인터페이스의 경우는   인터페이스를 구현해야 한다 라고 표현한다.

class GallexyS : public ISmartPhone{


public :

void Calling(char *no) { cout << "Calling with GallexyS" << endl;}


};


class GallexyS2: public ISmartPhone, public Mp3function{ //s2는 음악까지됨 


public :

void Calling(char *no) { cout << "Calling with GallexyS2" << endl;}


};

/*


class People{


public :

void UsePhone(GallexyS *p){p->Calling("010-9179-3197");}

void UsePhone(GallexyS2 *p){p->Calling("010-9179-3192");}

};

*/


int main(){


People p;

GallexyS s;

p.UsePhone(&s);

GallexyS2 s2;

p.UsePhone(&s2);


}

*/

Posted by k1rha
2012.08.15 13:28

#include<iostream>

//using namespace std;


//////////////////////////////////////////////////////////////////////

//  접근 변경자!

//////////////////////////////////////////////////////////////////////

// 1. 부모의 멤버를 물려 받을때 접근 지정자를 변경해서 물려 받게 하는 기술

//////////////////////////////////////////////////////////////////////


/*

class A {


private: int a;

protected: int b;

public: int c;



};

class B : public A{


};

int main(){

A a;

B b;

a.c = 10;

b.c = 10;


}

*/


#include<list>

//////////////////////////////////////////////////////////////////////////////////////////////////////

//list 가 있다. 

//그런데 스텍이 필요하다!

// 그럼 새롭게 만드는것보다 list를 한방향으로만 사용하면 stack 이다..list를 재사용하자

// LIST 클래스를 다른 클래스 stack 처럼 사용한다

//

//어댑터 패턴 : 기존 클래스의 인터페이스(함수 이름)을 변경해서 다른 클래스처럼 보이게 하는 디자인 기술.

//

//이럴때 list의 있는 함수는 쓰기 싫지만, 자신은 써야할떄 private 상속을 하면됨.

//private 상속 철학: 구현은 물려 받지만 (자식이 내부적으로 사용하지만 인터페이스는 물려받지 않겠다 : 

// :부모함수를 노출하지는 않겠다.

//////////////////////////////////////////////////////////////////////////////////////////////////////

/*

using namespace std;


template<typename T> class stack : private list<T>{

public:

void push(const T &a) {push_back(a);}

void pop() {pop_back();}

T & top() {return back();}


};


int main(){

stack<int> s;

s.push(10);

cout << s.top()<<endl;


}

*/

/*

/////////////////////////////////////////////////////////////////////

//s/w 재사용에는 상속 뿐만 아니라 포함도 있다.

//int 형외에 벡터도 가져오고 싶은데 

// 사용자편의를 위해서 디폴트를 int형으로 선언하고싶다! 

//아래와같이 코딩함

/////////////////////////////////////////////////////////////////////

using namespace std;

template<typename T,typename C=deque<int>> class stack{

C st;

public:

void push(const T&a) {st.push_back(a);}

void pop() {st.pop_back();}

T & top() {return st.back();}

};

int main(){

stack<int> s;

s.push(10);

cout << s.top();


}

*/



Posted by k1rha
2012.08.15 11:04

#include<iostream>

#include"memchk.h"

using namespace std;


//new를 재정의하는 다양한 기법



int main(){

int *p1 = new int;

int *p2 = new int;

int *p3 = new int;

delete p2;

/*


cout << __FILE__ << endl;

cout << __LINE__ << endl;

cout << __TIME__ << endl;

*/ //표준 C/C++ 에서 지원하는 메크로


return 0; // 다른 헤더에서 메임을 가짜로 바꿨으니.. 리턴0을 써줘야한다

}

====================================memchk.h==============================================


#include<iostream>

using namespace std;


struct MEM{


char file[256];

int line;

void * addr;

};


MEM mem[1000];

int count =0;

void * operator new (size_t sz , char *file , int line){

void *p = malloc(sz);

//할당정보를 배열에 보관한다.


mem[count].addr = p;

mem[count].line = line;

strcpy(mem[count].file, file);

++count;

return p;

}


void operator delete(void *p){


for(int i=0;i<count ; i++){

if(mem[i].addr ==p){

mem[i] = mem[count-1];

free(p);

--count;

break;

}

}

}

int Main();

int main(){

int ret = Main();  //사용자 메인함수는 단순 호출이고 그뒤에 내가 원하는 결과를 붙인다.


if(count == 0)cout << "메모리 누수가 없습니다"<<endl;

else{

cout << count << "개의 메모리 누수가 있습니다."<<endl;

for(int i=0;i<count;i++){

printf("%s(%d):%p\n",mem[i].file, mem[i].line, mem[i].addr);

}

}

return ret;

}


#define main Main   //이후에 메인은 메인이 아니다!!!  그 메인의 리턴값 이후에 무언가를 출력시킴 

#define new new(__FILE__, __LINE__)  //new를 디파인

int *p = new int;


Posted by k1rha
2012.08.15 11:02

#include<iostream>


using namespace std;


/////////////////////////////////////////////////

//New 이야기

//1 New 의 동작 방식

//(A)operator new() 함수를 사용해서 메모리를 할당 한후

//(B)(A) 가 성공했고 객체 였다면 생성자 호출

//(C) 주소를 해당 타입으로 캐스팅해서 리턴.

//

//delete

//(A) 소멸자 호출

//(B) operator delete()를 사용해서 메모리 해지

//

//////////////////////////////////////////////////////////////////

class Test{


public:

Test(){cout<<"Test()"<<endl;}

~Test(){cout<<"~Test()"<<endl;}

};


int main(){

//생성자 소ㅕㄹ자의 호출없이 메모리만 할당/해지하는 방법

//결국 C의 malloc과 유사


Test *p = static_cast<Test *>(operator new( sizeof(Test));

operator delete(p);


}

=====================================================================================


Posted by k1rha
2012.08.14 17:43

#include<iostream>

using namespace std;


/////////////////////////////////////////////////////////////

// 변환 이야기

// Point -> int : 변환 연산자

// int -> Point : qusghks todtjdwk (인자가 1개인 생성자)

////////////////////////////////////////////////////////////


class Point{



int x, y;


public:

Point() :x(0),y(0){}

Point(int a , int b):x(a),y(b){}


//변환 연산자 : 객체를 다른 타입으로 암시적/ 명시적 형변환 되게 한다.

// 변환 연산자는 리턴값을 표시하면 에러이다.

operator int(){


return x;

}


Point(int a) :x(0),y(0){} // 변환생성자 

};

/*

int main(){


double d = 3.4;

int n =d;


Point p(1,2);

int n2 = p; //p.operator int() 가 있으면 된다.

}

*/


int main(){

Point p1(1,2);

int n =p1; // p1.operator int() 이므로 OK 

//Point -> int 변환

// p1=n; // int -> Point 변환 

// 똑같은 의미에서 n.operator Point() 가 있으면 된다. 하지만 n 은 객체가 아니다 ㅠㅠ


p1=n; // 변환 생성자 적용 후 int 형생성자가 있으면 가능하다!

//컴파일러가 임시 객체를 만들어서 집어넣은뒤 대입연산자를 통해 넣어주게 된다.

}



================================ 활용 법 ===========================================


#include<iostream>

using namespace std;


class OFile 

{


FILE *file;


public:


//모르는 연산자가 넘어오는 것을 방지하기 위해서.. 인자가 1개인 생성자가 암시적으로 변환을 일으키는 것을 막는다.

//explicit  // 단! 명시적 변환은 된다.

explicit OFile (const char *name , const char *mode = "wt"){

file = fopen (name ,mode);

}

~OFile(){fclose(file);}


void write(const char *s){fwrite(s,1,strlen(s),file);}


//operator  // 차세대 C++ 은 변환  연산자 앞에도 explocit 를 붙일 수 있따.

operator FILE*(){return file;} // 변환 연산자?!!!


};


/////////////////////////////////////////////////////////////////////

//변환 연산자의 적절한 예시

////////////////////////////////////////////////////////////////////

/*

int main(){

OFile f("a.txt");

f.write("hellow");

int n=10;

fprintf(f,"n=%d",n); //OFILE 이 파일포인터로 변환만 될수 있따면 ..ㅠㅠ 벼..변환 연산자?!

///////////////변환 연산자 후엔 다 슬수 있다.////////////////////

fputs("world",f);



////////////////다른 예를 들어보자! ////////////////////////////////////////////

// char s[10]="hello";

// String s2="aaa";

// strcpy(s,s2); //?



}


*/

void foo(OFile f){


}

int main(){


OFile f("a.txt");

foo(f); // 당연하다!!!! 

//////////////explicit 적용전 ///////////////////////

/// foo("hellow"); //!?

//error 가 나와야한다

//잘된다!! char * -> OFile 이 면 된다! 

//////////explicit 적용후는 안됨 ///////////////////////


foo((OFile)"hellow"); //의도적으론 된다.

}

==================================================================================================

Posted by k1rha
2012.08.14 16:52

#include<iostream>

#include<algorithm>


using namespace std;


///////////////////////////////////////////////////////////////////////////////

// STL 의 sort() 는 마지막 인자가 T로 되어 있다.

//

//

//

///////////////////////////////////////////////////////////////////////////////


// 아래 코드의 단점 인라인 처리가 안된다?!

/*

int cmp1(int a, int b) {return a-b;}

int cmp2(int a, int b) {return b-a;}


int main(){


int x[10] = {1,2,3,4,5,6,7,8,9,10};

sort(x,x+10,cmp1);  //sort(int *, int *, int(*)(int,int)) 함수 생성 

sort(x,x+10,cmp2); //sort(int *, int*, int(*)(int,int))




}

*/


//////////////////////////////////////////////////////////////////////////////

// 이미 있는 STL 이다!!

// #include <functional> 다있다! 다있따!  //less<> , greater<>

////////////////////////////////////////////////////////////////////////////

template<typename T>struct less{

bool operator()(T a,T b){return a<b;}

};


struct greater {bool operator()(int a, int b){return a>b;}};


int main(){


int x[10] = {1,2,3,4,5,6,7,8,9,10};

less<int> cmp1;

greater cmp2;


sort(x,x+10,cmp1); //sort(int *, int *, less) 함수 생성

sort(x,x+10,cmp2); //sort(int *, int*, greater) 함수 생성




}

=====================================================================

함수객체이야기

=====================================================================

#include<iostream>

#include<algorithm>


using namespace std;


///////////////////////////////////////////////////////////////////////////////

// STL 의 sort() 는 마지막 인자가 T로 되어 있다.

//

//

//

///////////////////////////////////////////////////////////////////////////////


// 아래 코드의 단점 인라인 처리가 안된다?!

/*

int cmp1(int a, int b) {return a-b;}

int cmp2(int a, int b) {return b-a;}


int main(){


int x[10] = {1,2,3,4,5,6,7,8,9,10};

sort(x,x+10,cmp1);  //sort(int *, int *, int(*)(int,int)) 함수 생성 

sort(x,x+10,cmp2); //sort(int *, int*, int(*)(int,int))




}

*/


//////////////////////////////////////////////////////////////////////////////

// 이미 있는 STL 이다!!

// #include <functional> 다있다! 다있따!  //less<> , greater<>

////////////////////////////////////////////////////////////////////////////

template<typename T>struct less{

bool operator()(T a,T b){return a<b;}

};


struct greater {bool operator()(int a, int b){return a>b;}};


int main(){


int x[10] = {1,2,3,4,5,6,7,8,9,10};

less<int> cmp1;

greater cmp2;


sort(x,x+10,cmp1); //sort(int *, int *, less) 함수 생성

sort(x,x+10,cmp2); //sort(int *, int*, greater) 함수 생성




}


/////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////

//절대값 오름 차순시?

/////////////////////////////////////////////////////////////

template <typename T>struct absLess{

inline bool operator()(T a, T b){return abs(a) < abs(b);}


};


int main(){


int x[10] = {1,3,5,7,9,-2,4,6,8,10};

//절대값 오른차순으로 소트하고싶다.

absLess<int> cmp;

sort(x,x+10,cmp);

}

Posted by k1rha
2012.08.14 15:13

#include<iostream>

using namespace std;

/////////////////////////////////////////////////////////////////////////////////

//STL 알고리즘

//guswo C++ 의 대부분의 라이브러리는 Ferneric 을 중요시 합니다 (STL 안드로이드 등) 

//

// Generic 이란 무엇인지 생각해 봅시다

//

// 1. 알고리즘 만들기

//

///////////////////////////////////////////////////////////////////////////////////


/*

//1단계 strchr() 의구현

//검색구간 : NULL 로 끝나는 문자열, ㅜㅕㅣㅣdms rjatordp vhgka dksehlsek.

//구간의 표현 : 포인터 

//구간의 이동 : 전위형 ++

//실패의 전달 : 0(NULL 포인터 )

//


char * xstrchr(char *s,char c){

while( *s !=0 && *s!=c)

++s;


return *s ==0 ? 0 : s;

}


int main(){



char s[] = "abcdefg";

char *p = xstrchr(s,'c');

cout << *p <<endl;

}



*/


/*

//////////////////////////////////////////////////////////////////////////////

//2단계 구현  일반화 - 부분 문자열도 검색이 가능하게 만드는 방법

// 검색 구간 : [fist , last) 사이의 문자열, ㅣㅁㄴㅅ sms rjatordp vhgkadksehla

// 구간의 표현 : 포인터

// 구간의 이동 : 전위형 ++

// 실패의 전달 : 0 (NULL)

//////////////////////////////////////////////////////////////////////////////

char * xstrchr(char *first, char *last , char value){

while(first !=last && *first !=value)++first;

return first == last ? 0 : first;

}

int main(){


char s[] ="abcedfg";

char * p = xstrchr(s,s+5,'c');

cout<< *p <<endl;


}

*/


/*

//////////////////////////////////////////////////////////////////////////////

//2단계 template 이용하기

//문제점 : 1 . 검색 구간의 타입과 검색 대상의 타입이 연관되어 있다.

//해결책 :  double 에 배열에서 int를 검색할 수 없다. 구간의 타입과 검색의 타입을 분리하자!

//

//문제점 : 2. T* 라고 하면 구간은 반드시 진짜 포인터로만 표현 되어야 한다.

//     스마트 포인터를 사용 할 수 없다.

//

/////////////////////////////////////////////////////////////////////////////

template <typename T> T* xfind(T *first, T* last , T value){

while(first !=last && *first !=value)++first;

return first == last ? 0 : first;

}


int main(){


double x[10] = {1,2,3,4,5,6,7,8,9};

double *p = xfind(x, x+10,5.0);

cout << *p << endl;



}

*/


////////////////////////////////////////////////////////////////////////////////

/// 검색내용과 검색부분을 분리해내자! 그렇게되면 스마트 포인터도 사용 할 수있다.

// 검색 구간 : [first, last) 모든 타입의 배열의 부분구간

// 구간의 표현 : 포인터 , 스마트 포인터(단  == , != , * , ++ 4개의 연산자 지원이 되느 스마트 포인터여야 한다.

//

//////////////////////////////////////////////////////////////////////////////

//

//실패의 전달 : last (past the end 라고 부르기도 한다. 마지막검색 다음 요소 

//////////////////////////////////////////////////////////////////////////////////////////////

//

// 이..이것슨!! STL 의 find() 알고리즘이다!!! 

//

///////////////////////////////////////////////////////////////////////////////////////////

template<typename T1, typename T2> T1 xfind(T1 first, T1 last, T2 value){


while(first !=last && *first !=value)++first;

return first;

}


int main(){


double x[10] = {1,2,3,4,5,6,7,8,9};

double *p = xfind(x, x+10,5.0);

cout << *p << endl;


}

Posted by k1rha
2012.08.14 13:59

#include<iostream>

using namespace std;


/*

class Car{


int mCount;

public :

Car() : mCount(0){}


void incStrong(){--mCount;}

void decStrong(){

if(--mCount ==0)delete this;

}

~Car(){cout<<"Car 파괴 "<<endl;}


};

*/


////////////////////////////////////////////////////////////////////////////////////////

/// 안드로이드 프레임웤에서는 모든 클래스가 RefBase 클래스를 상속받아 사용되게 되어있다.

////////////////////////////////////////////////////////////////////////////////////////

class RefBase{


int mCount;

public :

RefBase() : mCount(0){}


void incStrong(){++mCount;}

void decStrong(){

if(--mCount ==0)delete this;

}

virtual ~RefBase(){cout<<"Red 파괴 "<<endl;}


};


class Car : public RefBase{



}

template<typename T> class sp

{

T * m_ptr;

public:

sp(T *other =0):m_ptr(other) {if(m_ptr)m_ptr->incStrong();}

sp(const sp &p):m_ptr(p.m_ptr) {if(m_ptr)m_ptr->incStrong();}

~sp() {if(m_ptr)m_ptr->decStrong();}


T *operator->(){return m_ptr;}

t& operator *(){return *m_ptr;}


}

int main(){


sp<Car> p1 = new Car;

sp<Car> p2=p1;


/*

Car *p1 = new Car;

p1->incStrong(); //객체 생성후 무조껀 1을 증가하자


Car *p2 = p1;

p2->incStrong(); //복사후 1을 증가하자


p1->decStrong(); //3. 모든 포인터는 사용후 1감소하자.

p2->incStrong();

*/

}

Posted by k1rha
2012.08.14 13:58

#include<iostream>

using namespace std;


//1. template 로 만들게 된다!! 당근이징 

//2. 얕은 복사를 해결 해야 한다.

//  (A) 깊은 복사

//  (B) 참조 계수

//  (C) 소유권 이전

//  (D) 복사금지 



/*

template <typename T>class ptr{

T *obj;


public:

ptr(T *p=0):obj(p){}

T *operator->(){return obj;}

T& operator*() {return *obj ;}


~ptr(){delete obj;}

};

//


int main(){

ptr<int> p1 = new int;

*p1 = 10;

cout << *p1 << endl;



}

*/

/*

////////////////////////// 복사 금지 ///////////////////////////////

// boost 의 scoped_ptr<> 이 이정책을 사용한다.

//장점 : 가볍다.

//단점 : 단지 자원곤리만 책임지고 대입 , 복사등이 불가능하다.

////////////////////////////////////////////////////////////////////


template <typename T>class scoped_ptr{

T *obj;

scoped_ptr(const scoped_ptr &p);

void operator = (const scoped_ptr &p);


public:

scoped_ptr(T *p=0):obj(p){}

T *operator->(){return obj;}

T& operator*() {return *obj ;}


~scoped_ptr(){delete obj;}

};


//void foo(scoped_ptr<int> p2); //불편함




int main(){

scoped_ptr<int> p1 = new int;

*p1 = 10;

cout << *p1 << endl;


//ptr<int> p2= p1; /// 컴파일 에러!! 절대 이렇게는 사용하지 마시요~ 라는 뜻 

}


*/

/*

//////////////////////////////////////// 소유권 이전 ///////////////////////////////

//#include<memory> // 이안에 auto_ptr 이 있다!!

//

/////////////////////////////////////////////////////////////////////////////////////

template <typename T>class Auto_ptr{

T *obj;


public:

//소유권 이전의 전략

Auto_ptr(ptr & p): obj(p.obj){

p.obj=0;

}


Auto_ptr(T *p=0):obj(p){}

T *operator->(){return obj;}

T& operator*() {return *obj ;}


~Auto_ptr(){delete obj;}

};


//void foo(scoped_ptr<int> p2); //불편함




int main(){

Auto_ptr<int> p1 = new int;

*p1 = 10;

cout << *p1 << endl;


Auto_ptr<int> p2= p1; //이제 자원은 p2만 사용한다 (소유권 이전)

//cout << * p1 < endl;//error

cout << *p2<<endl; // ok



}

*/

/////////////////////////////////// 참조 계수 /////////////////////////////////////

// boost 에서 만들고 STL 에 새롭게 추가된 shared_ptr 입니다.

/////////////////////////////////////////////////////////////////////////////////////

template <typename T>class Auto_ptr{

T *obj;

int *pRef;


public:

//참조계수 전략


Auto_ptr(T *p=0):obj(p){

pRef = new int(1);


}

ptr(const ptr &p):obj(p.obj),pRef(p.pRef){

++(*pRef);

}


T *operator->(){return obj;}

T& operator*() {return *obj ;}

~Auto_ptr(){

if(--(*pRef)==0){

dlete obj;

delete pRef;

}

}

};


//void foo(scoped_ptr<int> p2); //불편함




int main(){

Auto_ptr<int> p1 = new int;

*p1 = 10;

cout << *p1 << endl;


Auto_ptr<int> p2= p1; //이제 자원은 p2만 사용한다 (소유권 이전)

//cout << * p1 < endl;//error

cout << *p2<<endl; // ok



}

Posted by k1rha
2012.08.14 13:57

#include<iostream>

using namespace std;


//////////////////////////////////////////////////////////////////////////////

// 스마트 포인터 : 임의의 객체가 다른 타입의 포인터 처럼 사용되는것

// 장점 : 진짜 포인터가 아니라 객체이다. 생성 복사 대입 소멸 모든과정을

// 사용자가 제어 할 수 있다. 대표적인 예가 소멸자에서의 자동 삭제 기능! 

//

//3. 주로 ->, * 연산자를 재정의해서 만들게 된다.


////////////////////////////////////////////////////////////////////////////


class Car

{

public:

void Go(){cout<<"car go"<<endl;}


};

//스마트 포인터 : 임의의 객체가 다른 타입의 포인터 처럼 사용되는 것.

class ptr{

Car *obj;

public:

ptr(Car *p=0):obj(p){}

Car *operator->(){return obj;}

Car& operator*() {return *obj ;}


~ptr(){delete obj;}

};


int main(){

ptr p=new Car;

p->Go(); // (p.operator->())Go() 이지만 

// (p.operator->())->Go() 처럼 해석된다.


/*

Car *p = new Car;

p->Go();

delete p;

*/


}

===================================================================================


Posted by k1rha
2012.08.14 11:51

#include<iostream>

using namespace std;


//연산자 재정의 개념

//철학 : 사용자 정의 타입도 빌트인 타입처럼 동작해야한다.

// 단축 표기의 미학!!

//1. + 도 결국 함수로 표현된다. operator +

//2. p1+p2 는 operator+(p1,p2)



///////////////////////////////// Friend 로 구성한 operator+//////////////////////////////////

/*

class Point{

int x,y;


public : 

Point(int a = 0, int b= 0) : x(a),y(b){}

//멤버변수가 아니더라도 private 에 접근 할수 있게 해달라.

friend Point operator+(const Point & p1, const Point &p2);

};

Point operator+(const Point &p1, const Point &p2){

return Point(p1.x +p2.x,p1.y+p2.y);

}

int main(){


Point p1(1,1);

Point p2(2,2);

Point p3= p1+p2; // operator+(p1,p2)가 있으면 된다.

//p1.operator+(p2) 라고 해석하기도 한다.


Point p4 = p1+5;

Point p5 = 5 +p1;

}

*/


///////////////////////멤버로 구성한 operator+ /////////////////////////////////


class Point{

int x,y;


public : 

Point(int a = 0, int b= 0) : x(a),y(b){}

//멤버변수가 아니더라도 private 에 접근 할수 있게 해달라.

Point operator+(const Point &p){

return Point (x + p.x, y + p.y);

}

};


int main(){


Point p1(1,1);

Point p2(2,2);

Point p3= p1+p2; // operator+(p1,p2)가 있으면 된다.

//p1.operator+(p2) 라고 해석하기도 한다.



Point p4 = p1+5;


//Point p5 = 5+p1;  //에러가 뜬다? why? 다음시간에 배움

}

//0. -,(),[],-> : 반드시 멤버여야 한다.

//1. 단항 : 멤버가 좋다

//2. 이항중 : += , -= , *= 등은 멤버가 좋다.

//3. 2를 제외한 이항 : 전역이 좋다.

//

//철학은 객체의 상태가 변경되면 멤버가 좋다!! ++a; a+=b; a+b;




=========================================================================================



#include<stdio.h>




//cout 의 원리


class ostream{


public :

ostream& operator<<(int n) {printf("%d",n);return *this;}

ostream& operator<<(const char *s ) {printf("%s",s);return *this;}

ostream& operator<<(ostream &(*f)(ostream &)){

f(*this);

return *this;

}

};

ostream cout;

ostream& end (ostream& os){

os<<"\n";

return os;

}

ostream& tab (ostream& os){

os<<"\t";

return os;

}


int main(){


int n =10;


cout<< n <<tab <<end; //cout.operator <<(n)

cout << "hello"; //cout.operator <<("hello")


}



Posted by k1rha
2012.08.14 10:38

#include<iostream>


using namespace std;



///////////////////////////////////////////////////////////////////////////////////////////

// 객체의 얕은 복사 이야기

// 1. 생성자에서 자원을 획득할 경우, 소멸자에서 자원을 반납하자! RAII

// RAII : resource acquision is initialize ( 자원을 획득하는 것은 객체의 초기화 이다.)

// 2. 클래스 내부에 포인터 멤버가 있다면 컴파일러가 제공하는 복사 생성자는 얕은 복사 현상을 일으킨다.

// 사용자는 반드시 이문제를 해결해야 한다.

//

// 3. 해결책

// (A) 깊은 복사 

// (B) 참조 계수

// (C) 소유권 이전 

// (D) 복사 금지

//

///////////////////////////////////////////////////////////////////////////////////////////

/*

class Cat{


char *name;

int age;


public : 

Cat (const char *n, int a): age(a){

name = new char[strlen(n)+1];

strcpy(name,n);


}

~Cat (){delete[] name;}

};

int main(){

Cat c1("NABI",2);

Cat c2(c1); //런타임에러 디버그 모드에서.. //포인터만 복사.. 하는경우는?! shallow copy 얕은 복사를 한다.

//이럴때는 소멸자에서 같은 메모리를 두번 지우려고 한다.

}


*/


///////////////// (A) 깊은 복사 /////////////////////////////////////

/*

class Cat{


char *name;

int age;


public : 

//깊은 복사를 구현한 복사 생성자 


Cat(const Cat & c ): age(c.age) // 1. 포인터가 아닌 멤버는 그냥 복사

{

name = new char[strlen(c.name+1)];

strcpy(name, c.name); // 메모리를 복사

}

Cat (const char *n, int a): age(a){

name = new char[strlen(n)+1];

strcpy(name,n);


}

~Cat (){delete[] name;}

};

int main(){

Cat c1("NABI",2);

Cat c2(c1); //런타임에러 디버그 모드에서.. //포인터만 복사.. 하는경우는?! shallow copy 얕은 복사를 한다.

//이럴때는 소멸자에서 같은 메모리를 두번 지우려고 한다.

}*/


/*

/////////////////////////////////////////////////////////////////////////////////////


////////////////// (B)참조계수법: 메모리를 복사하지말고 카운트를 하자! //////////////////

class Cat{


char *name;

int age;

int *pRef;

public : 

// 참조 계수를 기반으로 만들어진 복사 생성자

Cat(const Cat&c) : name (c.name), age(c.age),pRef(c.pRef){

++(*pRef);

}

Cat (const char *n, int a): age(a){

pRef = new int(1); //1개를 1로 초기화 

name = new char[strlen(n)+1];

strcpy(name,n);


}

~Cat (){

if(--(*pRef)==0){


delete[] name;

delete pRef;

}

}

};

int main(){

Cat c1("NABI",2);

Cat c2(c1); //런타임에러 디버그 모드에서.. //포인터만 복사.. 하는경우는?! shallow copy 얕은 복사를 한다.

//이럴때는 소멸자에서 같은 메모리를 두번 지우려고 한다.


//c1.name = "AAA"; //이순간 C1 C2는 자원(이름)을 분리해야한다.

//copy on write (COW)라는 기술~

}


*/

///////////////////////////////////////////////////////////////////////////////////////////



//////////////////////////// (C) 소유권이전의 복사생성자 기술1 ////////////////////////////

/*

class Cat{


char *name;

int age;


public :


//swap 같등을 만들때 아주 좋은 방식이다! 차세데 C++ ㅇ는 move 생성자라고 부른다

// 현재는 C++ 표준인 auto_ptr<> 이 이기술을 사용한다


//소유권 이전의 복사 생성자 기술!! 

Cat(Cat & c):name(c.name),age(c.age) //얕은 복사

{

c.name=0;

c.age=0;


}

Cat (const char *n, int a): age(a){

name = new char[strlen(n)+1];

strcpy(name,n);


}

~Cat (){delete[] name;}

};

int main(){

Cat c1("NABI",2);

Cat c2(c1); //런타임에러 디버그 모드에서.. //포인터만 복사.. 하는경우는?! shallow copy 얕은 복사를 한다.

//이럴때는 소멸자에서 같은 메모리를 두번 지우려고 한다.

}


*/

/*

//////////////////////////////////(D) 복사금지 기법///////////////////////////////////////

class Cat{


char *name;

int age;

//private 복사 생성자 .. 복사 금지 할떄 사용하는 기술

Cat (const Cat & c); //선언만한다 1.일단선언이 있으므로 컴파일러는 디폴트복사를 제공하지 않는다.

//2.어딘가에서 호출하는 코드가 있으면 구현이 없으므로 링크 에러이다.

//  멤버함수에서도 호출 할 수 없다.



//보통 복사를 금지하면 대입도 금지한다

void operator=(const Cat&);

public :

void foo(){

// Cat c1("A",10);

// Cat c2(c1); //OK 에러를 내게한다.


}

Cat (const char *n, int a): age(a){

name = new char[strlen(n)+1];

strcpy(name,n);


}

~Cat (){delete[] name;}

};

int main(){

Cat c1("NABI",2);

// Cat c2(c1); //캄파일 시간에러가 나오게 하자! 



}



//////////////////////////////////////////////////////////////////////////////////////////////


*/



////////////////////////////////////////////////////////////////////////////////

// 복사 연산자는 너무나 유용하기 때문에 따로 클래스를 만들어 사용하는경우가 많다,

//

//////////////////////////////////////////////////////////////////////////

class uncopyable

{

private:

uncopyable(const uncopyable &);

void operator=(const uncopyable &);

};

//이것을 상속 받아 사용하면된다. 


class Cat : private uncopyable{


char *name;

int age;


public :

Cat (const char *n, int a): age(a){

name = new char[strlen(n)+1];

strcpy(name,n);


}

~Cat (){delete[] name;}

};

int main(){

Cat c1("NABI",2);

// Cat c2(c1); //캄파일 시간에러가 나오게 하자! 



}

///////////////////////////////////////////////////////////////////////////


Posted by k1rha
2012.08.14 10:37

#include<iostream>

using namespace std;

////////////////////////////////////////////////////////////////////////

//

//복사 생성자 이야기 

//1. 사용자가 복사 생성자를 만들지 않으면 컴파일러가 만들어 준다.

//2. 기본적으로 모든 멤버를 복사 해준다.

//3. C++ 에서 복사생성자가 사용되는 것은 3가지 경우입니다.

// (A) 자신의 타입으로 초기화 될떄 : Point p2(p1)

// (B) 함수인자로 ㄱㄱ체가 값으로 전달될떄 : void foo(Point)

// void foo(const Point &) 를 사용하면 복사생성자 호출을 막을 수 있다.

// Const & 의 장점 : 1. 메모리사용량이 줄어든다.

// 2. 복사 생성자 소멸자의 호출을 막아서 성능 향상된다.

//

// (C)함수가 객체를 값으로 리턴할때 - 임시객체 때문에 복사 생성자가 호출된다. 

// 그럴때 RVO를 사용하면 막을 수 있다.

//

///////////////////////////////////////////////////////////////////////////

/*

class Point{



int x,y;

public:

Point() :x(0),y(0){}

Point(int a, int b) :x(a),y(b){}

//zjavkdlffjsms dkfo ahdiddml todtjdwkfmf wprhdgownsek.

Point(const Point &p):x(p.x),y(p.y){}


};


int main(){


Point p1;

Point p2(1,2);

Point p3(p2); //Point(Point) 모양의 생성자가 필요하다!!


}


*/



/*

class Point{



int x,y;

public:

Point() {cout<<"생성자 1"<<endl;}

Point(int a, int b) {cout<<"생성자 2"<<endl;}

//zjavkdlffjsms dkfo ahdiddml todtjdwkfmf wprhdgownsek.

Point(const Point &p) {cout<<"복사 생성자"<<endl;}

~Point() {cout<<"소멸자"<<endl;}


};

//void foo(Point p){  // 복사생성자와 소멸자가 호출되어 객체가 한번더 호출된다.

void foo(const Point &p)  //const는 그대로 유지되기떄문에 복사생성자가 호출되지 않는다.

{

cout<<"foo"<<endl;

}


int main(){


cout<<"start"<<endl;

Point p1;

cout << "AAA"<<endl;

foo(p1);

cout<<"BBB"<<endl;



}*/



///////////////////////////////////////////////////////////////////////////////////////////////////

///

/// 아래의 코드에 복사 생성자가 들어가있다!! why? return p1 에서 복사생성자에 복사에서 보내기 떄문이다! 

// 1 생성자1 -> AAA -> 생성자2 -> foo -> 복사생성자 -임시객체 -> 소멸자 - 소멸자(임시객체)->BBB-> 소멸자 P

//

////////////////////////////////////////////////////////////////////////////////////////////////////

/*

class Point{



int x,y;

public:

Point() {cout<<"생성자 1"<<endl;}

Point(int a, int b) {cout<<"생성자 2"<<endl;}

//zjavkdlffjsms dkfo ahdiddml todtjdwkfmf wprhdgownsek.

Point(const Point &p) {cout<<"복사 생성자"<<endl;}

~Point() {cout<<"소멸자"<<endl;}


};


Point foo()

{

Point p1(1,2);

cout << "foo" << endl;

return p1;   // 임시 객체를 통해 리턴한다.

}



int main(){


Point p;

cout << "AAA"<<endl;

p=foo();

cout<<"BBB"<<endl;


}

*/

//////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////

//위와같은 문제를 줄여주기 위해 RVO(return value optimization) 이라고 불리는 기술을 사용한다.

///////////////////////////////////////////////////////////////


class Point{



int x,y;

public:

Point() {cout<<"생성자 1"<<endl;}

Point(int a, int b) {cout<<"생성자 2"<<endl;}

//zjavkdlffjsms dkfo ahdiddml todtjdwkfmf wprhdgownsek.

Point(const Point &p) {cout<<"복사 생성자"<<endl;}

~Point() {cout<<"소멸자"<<endl;}


//Point(Point p){} // 이렇게하면 복사생성자가 재귀적으로 무한히 호출되므로 컴파일 에러가 뜬다.

//point(Point &p){} // OK~!

};


Point foo()

{


/////////////////////////////////////////////////////////////////////////////////

// 이름이 있는 객체도 RVO로 자동 리턴된다 NRVO 기술 (Named Return value Optimization)

// VC++ 2005 부터 지원되는 최적화 기술

//

/////////////////////////////////////////////////////////////////////////////////////

// Point p1(1,2);

// cout << "foo" << endl;

// return p1;   // 임시 객체를 통해 리턴한다.  // 리턴하면 성능이 좋치 않다.

//릴리즈 모드를 하면 알아서 RVO 모델로 최적화가 된다. 

cout << "foo"<<endl;

return Point(1,2);

}

int main(){


Point p;

cout << "AAA"<<endl;

p=foo();

cout<<"BBB"<<endl;


}


Posted by k1rha
2012.08.13 17:48

#include<iostream>


#include<Windows.h>


using namespace std;


// 멀티 쓰레드 프로그램을 C++ 클래스로 래핑해 보자 - 안드로이드 원리 

/*

DWORD __stdcall foo( void *p){

return 0;

}


int main(){

CreateThread(0,0,foo,"A",0,0);

}

*/


class Thread{

public: 

void start(){

CreateThread(0,0, _threadLoop,this,0,0);

}


//아래 함수가 static 일수밖에 없는 이유를 알아야 한다

// C 의 콜백함수의 개념을 클래스화 할 때는 결국 static 함수로 해야한다.

static DWORD __stdcall _threadLoop(void *p){

Thread * pThis = static_cast<Thread *>(p);


pThis -> threadLoop();  //this -> theadLoog()로 변경 될 수 있어야 한다.

return 0;

}

virtual void threadLoop(){}


};

//----------------------------------------------------

// 이제 위 라이브러리 사용자는 Thread 의 자식을 만들어서 threadLoop() 가상함수를 재정의한다.

class MyThread : public Thread{

public :

virtual void threadLoop(){

for(int i=0;i<10;i++){

cout << i << endl;

Sleep(1000);


}

}

};


int main(){


MyThread t;

t.start();

int n;

cin >> n;


}


Posted by k1rha
2012.08.13 17:47

#include<iostream>


#include<Windows.h>


using namespace std;


// 멀티 쓰레드 프로그램을 C++ 클래스로 래핑해 보자 - 안드로이드 원리 

/*

DWORD __stdcall foo( void *p){

return 0;

}


int main(){

CreateThread(0,0,foo,"A",0,0);

}

*/


class Thread{

public: 

void start(){

CreateThread(0,0, _threadLoop,this,0,0);

}


//아래 함수가 static 일수밖에 없는 이유를 알아야 한다

// C 의 콜백함수의 개념을 클래스화 할 때는 결국 static 함수로 해야한다.

static DWORD __stdcall _threadLoop(void *p){

Thread * pThis = static_cast<Thread *>(p);


pThis -> threadLoop();  //this -> theadLoog()로 변경 될 수 있어야 한다.

return 0;

}

virtual void threadLoop(){}


};

//----------------------------------------------------

// 이제 위 라이브러리 사용자는 Thread 의 자식을 만들어서 threadLoop() 가상함수를 재정의한다.

class MyThread : public Thread{

public :

virtual void threadLoop(){

for(int i=0;i<10;i++){

cout << i << endl;

Sleep(1000);


}

}

};


int main(){


MyThread t;

t.start();

int n;

cin >> n;


}


Posted by k1rha
2012.08.13 16:59

#include<iostream>

using namespace std;


//주제 10 싱글톤 디자인 기법

//1. 개념 : 오직 한개만을 만들수 있게 한 디자인

//오직 한개의 객체가 static 메모리에 있다. meyer 의 싱글톤이라고 부름.

/*

class Cursor

{

private:

Cursor(){} //즉 객체를 한개도 만들수 없다!


Cursor(const Cursor &); //복사 생성자 금지


public:

static Cursor & getInstance(){

static Cursor instance;

return instance;

}

};


int main(){

Cursor &c1 = Cursor::getInstance();


Cursor &c2 = Cursor::getInstance();


//Cursor c3= c1;//하지만 복사 생성자가 가능하다 


cout<< &c1 << endl;


}

*/


/*

///힙에서 만드는 싱글 톤  - 안드로이드 버전 

//내가 알고있던 싱글톤

class Cursor

{

private:

Cursor(){} //즉 객체를 한개도 만들수 없다!


Cursor(const Cursor &); //복사 생성자 금지

static Cursor * pInstance ; 

public:

static Cursor & getInstance(){

if(pInstance==0){

pInstance = new Cursor;

}

return *pInstance;

}

};

Cursor * Cursor::pInstance=0;


int main(){

Cursor &c1 = Cursor::getInstance();


Cursor &c2 = Cursor::getInstance();


//Cursor c3= c1;//하지만 복사 생성자가 가능하다 


cout<< &c1 << endl;


}*/

/*

/////////////////////////////////////////

// 싱글톤 여러개를 호출시 메크로로 만들기 

// 에러남 -_- 젠장..

/////////////////////////////////////////

#define DECLARE_SINGLETON(classname) private : classname(){ \

classname(const classname&); \

static classname *pInstance;\

public :\

static classname & getInstance();

#define IMPLEMENT_SINGLETON(classname)\

classname  *classname::pInstance =0;\

classname & classname::getInstance()\

{\

if(pInstance == 0)pInstance = new classname;\

return *pInstance;}



class Keyboard

{

DECLARE_SINGLETON(keyboard);

};

IMPLEMENT_SINGLETON(keyboard);


class Cursor

{

private:

Cursor(){} //즉 객체를 한개도 만들수 없다!


Cursor(const Cursor &); //복사 생성자 금지

static Cursor * pInstance ; 

public:

static Cursor & getInstance(){

if(pInstance==0){

pInstance = new Cursor;

}

return *pInstance;

}

};

Cursor * Cursor::pInstance=0;


int main(){

Cursor &c1 = Cursor::getInstance();


Cursor &c2 = Cursor::getInstance();


//Cursor c3= c1;//하지만 복사 생성자가 가능하다 


cout<< &c1 << endl;


}*/


//안드로이드 싱글톤 사용하기 

template <typename TYPE> class Singleton

{

protected:

Singleton(){} //즉 객체를 한개도 만들수 없다!

private:

Singleton(const Singleton &); //복사 생성자 금지

static TYPE * pInstance ; 

public:

static TYPE& getInstance(){

if(pInstance==0){

pInstance = new TYPE;

}

return *pInstance;

}

};

template<typename TYPE> TYPE * Singleton::pInstance=0;


class keyboard : public Singleton<keyboard>{  //mix in template !!


}



int main(){

keyboard & k = keyboard::getInstance();


}


=========================================== MIX IN template method ====================================

#include<iostream>

using namespace std;


// 문제점! 가상함수의 메모리 낭비가 크다!

/*

class Window{


public : 

void MessageLoop(){


int msg = 1;

switch(msg){

case 1: MouseMove();break; //this->MouseMove();

case 2: KeyDown(); break;

}

}

virtual void MouseMove(){

}

virtual void KeyDown(){}



};

//======================================================

class MyWindow : public Window

{

public :

void MouseMove(){ cout << "ouseMove"<<endl;}


}

int main(){


MyWindow w;

w.MessageLoop();

}

*/

////////////////////////////////////////////////////////////////

//virtual 없이 해결하기  부모는 자식의 이름을 알수는 없지만 템플릿을 사용하면 알수 있따.

///////////////////////////////////////////////////////////////


template<typename T> class Window{


public : 

void MessageLoop(){


int msg = 1;

switch(msg){

case 1: static_cast<T*>(this)->MouseMove();break; //this->MouseMove();

case 2: static_cast<T*>(this)->KeyDown(); break;

}

}

void MouseMove(){

}

void KeyDown(){}



};

//======================================================

class MyWindow : public Window<MyWindow>

{

public :

void MouseMove(){ cout << "ouseMove"<<endl;}


}

int main(){


MyWindow w;

w.MessageLoop();

}




Posted by k1rha
2012.08.13 15:47

#include<iostream>

using namespace std;

/*

//주제 9 상수 함수의 개념 

//1. 개념 : 모든 멤버를 상수 취급하는 함수

//2. 상수 객체는 상수 함수만 호출 할 수 있다.

//


class Point

{

public : 

int x,y;

Point(int a=0,int b=0):x(a),y(b){}


void Set(int a){x=a;}

void print() //const  는 아래 주석때문에라도 꼭 붙여야 한다.


{

//x=10; //error 함수안에서 모든 멤버는 상수이다.

cout << x << ","<<y<<endl;

}

};

int main(){


const Point p(1,2);

//p.x=10; //error 나와야 한다.

//p.Set(20); //error 나와야 한다 

//


//p.print(); //  호출 될 수 있으려면 반드시 print() 는 상수 함수로 해야 한다.


}

*/


//10 Const 와 Const 아닌것의 차이 

// 우리는 상수 객체를 안만듭니다?!  그렇다면 이건 어떠냐!

// 멤버 함수가 data의 값을 변경하지 않는다면 반드시 상수 함수로 해야한다.

//상수 함수는 선택이 아닌 필수이다.

///////////////////////////////////////////////////////////////////


class Rect{

int x,y,w,h;

public :

//int GetArea(){return w*h;}  //Rect 에 const 를 붙이면 반드시 여기도 붙여야 출력이 된다.

int GetArea() const{return w*h;}

};



//void foo( Rect &r){   //이걸 하게되면 객체가 변한다! 헐킈

void foo(const Rect &r){ //그래서 이걸 쓸수 밖에 없다! 그렇다면 getArea도 붙여줄 수 밖에없다.


int n = r.GetArea();

}


int main(){

Rect r;

foo(r);

int n=r.GetArea();

}

=============================================================================================================


#include<iostream>

using namespace std;


//상수함수 2

//1. 논리적 상수성!! (밖에서 보기엔 상수인데 논리적으로 내부 루틴은 상수가 아닌 현상

// 해결책!!

// (A) mutable : 상수 함수 안에서도 값을 변경할 수 있는 멤버 data

// (B) 변하는 것과 변하지 않는 것은 분리해야 한다.

// 변하는 것을 다른 구조체로 뽑아 낸다.


/*

//(A) 클래스 

class Point{


int x,y;

mutable char cache[32];

mutable bool cache_valid;


public :

Point(int a=0,int b=0):x(a),y(b),cache_valid(false){}

//객체를 문자열로 반환하는 함수 - > javam c# 에 있는 개념

char * toString() const

{

//static char s[32]// tjdsmd wjgkfmf dnlgks qkdwl 

//sprintf(s,"%d,%d",x,y);

if(cache_valid ==false){

sprintf(cache,"%d,%d",x,y);

cache_valid = true;

}

return s;

}

};


int main(){

const Point p(1,2);

cout << p.toString()<<endl;

cout << p.toString()<<endl;


}

*/

/*

//(B) 클래스 

//변하는것과 변하지 않는것은 분리 되어야한다.

// 이로써 mutable 을 사용하지 않고

//변하지 않는 변수들은 클래스로 뭉치고 변하는 값들은 구조체포인터로 빠진다. 

struct Cache{

char cache[32];

bool cache_valid;

}



class Point{


int x,y;

Cache * pCache;

public :

Point(int a=0,int b=0):x(a),y(b){

pCache = new Cache;

}

//객체를 문자열로 반환하는 함수 - > javam c# 에 있는 개념

char * toString() const

{

//static char s[32]// tjdsmd wjgkfmf dnlgks qkdwl 

//sprintf(s,"%d,%d",x,y);

if(pCache->cache_valid ==false){

sprintf(pCache->cache,"%d,%d",x,y);

pCache->cache_valid = true;

}

return pCache->cache;

}

};


int main(){

const Point p(1,2);

cout << p.toString()<<endl;

cout << p.toString()<<endl;


}*/



///////// 2. 문법정리 ////////////// 


class Test{

public : 


//동일 이름의 상수, 비상수 함수를 동수에 만들수 있다. 

void foo(){}

void foo() const{}

void goo() const;

};


void Test::goo() const{}  //반드시 붙여야 같은 상수 함수로 인식한다. 



int main()

{

Test t1;

t1.foo(); //1번, 없다면 2번 유드리 있게 변함

const Test t2;

t2.foo(); //2번, 없다면 에러이다. 

}




Posted by k1rha
2012.08.13 15:46

#include<iostream>


using namespace std;


////////////////////////////////////////////////////////////////////////////////

//생성자 정리 1. 

//1. 사용자가 만들지 않으면 컴파일러가 만들어준다.

// 인자가 없고 하는 일이 없는 생성자? (정말 하는 일이 없을까?)

//

//2. 하나의 생성자에서 다른 생성자를 호출 할 수 없다.!!

// C++ 2.0 (C++11 이라고 부름) 에서는 위임생성자라는 문법으로 가능함 

//

//3. 생성자는 명시적으로 호출할수 없다! . 다만 placement new를 사용하여 가능하다.

//4. 소멸자는 명시적으로 호출할수 있다. 왜필요할까?! (수요일쯤강의..)

////////////////////////////////////////////////////////////////////////////////

/*

class Point{

int x;

int y;


public :

Point() {x=0;y=0;}

Point(int a, int b) {x=a;y=b;}

}



int main(){


Point p1;

Point p2(1,2);


}*/



//3//

////////////////////////////////////////////////////////

class Point{

int x;

int y;


public :

Point() {cout << "생성자 " <<endl;}

~Point() {cout<<" 소멸자 "<<endl;}

};


int main(){



Point p;

//p.Point();  // Error !!  생성자를 명시적으로 호출 할 수 없다.

new (&p) Point; // 생성자를 명시적으로 호출하는 기술!  

//AKA  :  Placement new 라는 기술 입니다.

p.~Point(); // 된다!! 소멸자는 명시적으로 호출 할 수 있다.


}



//5. 객체 멤버의 생성자가 먼저호출되고 객체 자신의 생성자가 호출된다.




class Point{

int x;

int y;


public :

Point() {cout << "생성자 " <<endl;}

~Point() {cout<<" 소멸자 "<<endl;}

};


class Rect{

Point p1;

Point p2;

public :

Rect(){cout << "Rect()" << endl;}

};

int main(){

Rect r; //결과를 예측해봅시당

}





==================================================================================================

#include<iostream>

using namespace std;


///////////////////////////////////////////////////////////////////////////////////////

// 주제 8. 초기화 리스트

//1. 개념 : 생성자 뒤에 : 을 적고 멤버를 초기화 하는 것.

//2. 장점 : 대입이 아니라 진짜 초기화이다. 객체 형 멤버가 있다면 초기화 속도가 빨라진다.

//3. 꼭 필요할때가 있다.

//////////////////////////////////////////////////////////////////////////////////////

/*

class Point {


int x;

int y;


public : 

Point(int a =0, int b=0) : x(a),y(b) //여긴 초기화

{

//x=a; // 여긴 대입

//y=b;

}

};


int main(){

Point p(1,2);


// Object a = 0; // 초기화

// Object b; 

// b=0; // 대입



}

*/

/*

//반드시 초기화 리스트로 해야 하는경우! 

//(A) 클래스 내부에 const 나 참조 멤버가 있다면 초기화 리스트로 반드시 초기화 해야 한다.


class Point {


int x;

int y; 

//int y=0; ////이때는 초기화가 안된다 왜냐하면 객체가 아직 생성되지 않았기 떄문에 메모리를 잡지 않았기 때문이다.


const int c;//단 반드시 초기화 리스트로 초기화 해야한다.

//const int c=0; // error 이다   때문에 생성자 안에서 대입연산으로 초기화 해주는것도 불가능하다. 반드시 초기화리스트를사용!



public : 

Point(int a =0, int b=0) : x(a),y(b),c(0) //여긴 초기화

{

//x=a; // 여긴 대입

//y=b;

}

};


int main(){


//const int c; //error 반드시 초기화가 필요하다.

//


}*/


//(B) 디폴트 생성자가 없는 멤버를 객체로 가질떄 초기화 리스트에서 특정 생성자를 명시적으로 호출해야 한다.


class Point {


int x;

int y; 


public : 

Point(int a, int b){}//여긴 초기화

};


class Rect{

Point p1;

Point p2;

public: Rect(): p1(0,0),p2(0,0){}



};

int main(){


Rect r;

}






Posted by k1rha
2012.08.13 14:44

#include<iostream>

using namespace std;

/*

//버전 1. C 버전

//버전 1의 문제점 : stack 이 2개가 필요하다면?!  모든게 2개여야한다.

int buff[10];

int index = -1;


void push(int a) { buff[++index]=a;}

int pop() {return buff[index--];}


int main(){



push(10);

cout << pop()<<endl;


}

*/

/*

//버전 2  2개이상의 스택을 고려

//버전 2의 문제점!  : 보기에 복잡하다! 타입을 만들어 줘야한다

void push ( int * buff, int *index , int a){


buff[++(*index)]=a;


}

int main(){

int buff1[10], index1;

int buff2[10], index2;

push(buff2, &index1, 10);


}

*/


//버전 3 구조체로 스택을 구현! Main 함수가 깔끔해졌다!

/*

struct stack{


int buff[10];

int index;

};


void init(stack *s){s->index = -1 ; } 

void push(stack *s , int a){ s->buff[++(s->index)]=a;}

int main(){


stack s1, s2;

init(&s1);

push (&s1,10);



}

*/

/*

//버전 4 상태를 나타내는 data 와 상태를 조작하는 함수를 묶자!

// 버전 4의 문제점! 잘못사용했을 시?!  문제가 생긴다 main 함수에 s1.idex=100 이라고 입력하면 스택이 깨져버린다.

//

struct stack{

int buff[10];

int index;


void init() {index=-1;}

void push(int a) {buff[++index]=a;}

int pop() {return buff[index--];}


};


int main(){


stack s1,s2;

s1.init();

s1.push(20);

cout << s1.pop()<<endl;



}


*/

/*

//버전 5 외부의 잘못된 사용으로 부터 객체가 불안해 지는 것을 막는 방법!

// 접근지정자의 도입!!

// 객체지향의 3대 원칙중하나인 캡슐화이다.


struct stack{

private:

int buff[10];

int index;

public:

void init() {index=-1;}

void push(int a) {buff[++index]=a;}

int pop() {return buff[index--];}


};


int main(){


stack s1,s2;

s1.init();

s1.push(20);

//s1.index=100; // 에러가 뜬다!!

cout << s1.pop()<<endl;



}

*/


/*


//버전 6 객체의 초기화를 자동으로 하자! 

//생성자의 도입

//struct 는 디폴트 접근 지정자가 public 이고 

//class 는 디폴트 접근 지정자가 private 이다.


struct stack{

private:

int buff[10];

int index;

public:

stack() {index=-1;}

void init() {index=-1;}

void push(int a) {buff[++index]=a;}

int pop() {return buff[index--];}


};


int main(){


stack s1,s2;

//s1.init();

s1.push(20);

//s1.index=100; // 에러가 뜬다!!

cout << s1.pop()<<endl;



}



*/

/*

//버전 7 내부 버퍼의 크기는 사용자가 결정하는 것이 좋다.

// 동적 메모리 할당의 도입..

class stack{

private:

int * buff;

int index;

public:

stack( int sz = 10)

{

index=-1;

buff = new int[sz];

}

void init() {index=-1;}

void push(int a) {buff[++index]=a;}

int pop() {return buff[index--];}


};


int main(){


stack s1(100);

//s1.init();

s1.push(20);

//s1.index=100; // 에러가 뜬다!!

cout << s1.pop()<<endl;



}

*/

/*

//버전 8 동적 할당하고나니 메모리 해지가 필요하다?! 

// 소멸자의 도입 

class stack{

private:

int * buff;

int index;

public:

stack( int sz = 10)

{

index=-1;

buff = new int[sz];

}

void init() {index=-1;}

void push(int a) {buff[++index]=a;}

int pop() {return buff[index--];}


~stack(){

delete[]buff;

}

};


int main(){


stack s1(100);

//s1.init();

s1.push(20);

//s1.index=100; // 에러가 뜬다!!

cout << s1.pop()<<endl;



}

*/

/*


//버전 9 다양한 type의 Stack 을 자동 생성되게 하자! 

// template 도입!!


template<typename T> class stack

{

T *buff;

int index;


private:

int * buff;

int index;

public:

stack( int sz = 10)

{

index=-1;

buff = new int[sz];

}

void init() {index=-1;}

void push(T a) {buff[++index]=a;}

T pop() {return buff[index--];}


~stack(){

delete[]buff;

}

};


int main(){


stack<int> s1(100);

//s1.init();

s1.push(20);

//s1.index=100; // 에러가 뜬다!!

cout << s1.pop()<<endl;



}

*/



/*

//버전 9 좀더 객체화시키고 역할을 쪼갠다. 

template<typename T> class stack

{

T *buff;

int index;


private:

int * buff;

int index;

public:

stack( int sz = 10)

{

index=-1;

buff = new int[sz];

}

void init() {index=-1;}



void push(const T& a) {buff[++index]=a;}


//pop 이 제거와 리턴을 동시에 하면 절대 최적화 할수 없다. 분리하자!!

//T pop() {return buff[index--];}


//제거만하는 함수

void pop(){ --index;}

//리턴만 하는 함수

T &top() {return buff[index];}

//하나의 함수는 한가지 일만 할떄가 좋다.


~stack(){

delete[]buff;

}

};


int main(){


stack<int> s1(100);

//s1.init();

s1.push(10);

s1.push(20);

//s1.index=100; // 에러가 뜬다!!

cout << s1.top()<<endl;

s1.pop();

cout << s1.top()<<endl;

s1.pop();



}

*/


//버젼 10 이미 있다!!

#include<stack>  //C++ 표준인 STL의 STACK 클래스


int main(){


stack<int> s;

s.push(10);

s.push(20);


cout << s.top() << endl;

s.pop();

cout<<s.top() << endl;

s.pop();


}

//버젼 11 숙제!! 배열로 스택을 구현하면 미리 할당을 해줘야한다! 

//버전 10의 내부 구조를 싱글 링크드 리스트로 변경해보기


Posted by k1rha