2012. 8. 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. 8. 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. 8. 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. 8. 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. 8. 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. 8. 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. 8. 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. 8. 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. 8. 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. 8. 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