2012. 8. 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. 8. 13. 21:48

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

2012. 8. 13. 21:44

Using php://filter for local file inclusion

I came across a website where the site was vulnerable to LFI (local file inclusion) however the inclusion was done using a require_once and the script appended a .php extension to the end of the file; furthermore it was not vulnerable to null byte injection which meant that if I did include a file that:

  1. The file would have to be valid PHP syntax
  2. I would not be able to see anything contained between <? ?> tags
  3. Anything I could include would be executed.
  4. The file would have to end in the PHP extension

I tried to see if I could include remote files by specifying a URL as the parameter, sadlyallow_url_include was turned off so that failed. When I specified a valid PHP page it simply returned the normal page as expected.

The solution that allowed me to view the source of any PHP file was to use the functionphp://filter/convert.base64_encode/resource which has been available since PHP 5.0.0

1http://www.example.com/index.php?m=php://filter/convert.base64-encode/resource=index

This forces PHP to base64 encode the file before it is used in the require statement. From this point its a matter of then decoding the base64 string to obtain the source code for the PHP files. Simple yet effective..


Once you’ve got the source code for one file you can inspect it for further vulnerabilities such as SQL injections and additional PHP files referenced via include or require.

  • delicious
  • digg
  • facebook
  • linkedin
  • reddit
  • stumble
  • tumblr
  • twitter
This entry was posted in PHP and tagged . Bookmark the permalink.

3 Responses to Using php://filter for local file inclusion

  1. JOhn says:

    That’s pretty slick ;)

    I have a feeling that this can be prevented by using basename();

    1<?php
    2if(isset($_GET['m'])){
    3    $file basename($_GET['m']);
    4    require_once '$file';
    5}

    What are your thoughts on that?

    • Phil says:

      If you just use basename the strings going to end up as “resource=index.php”, checking to see if the file exists (using file_exists) is probably a safer method as it will return false for any php://filter files. A quick preg_match couldn’t hurt either…

      1if (preg_match("/^[A-Z0-9]+$/i"$_GET['m'])) {
      2    if (file_exists($_GET['m'])) {
      3        require_once($_GET['m']);
      4    }
      5}
  2. Frost says:

    Why not just have a white list array, even the `$_GET['m']` could produce unwanted results, and better to not leave it up to that.

    1$whiteList array('index' => 'index.php''about' =>'about.php');
    2if (in_array($_GET['m'], $whiteList)) {
    3      require_once($whiteList[$_GET['m']]);
    4}else {
    5      require_once($whiteList['index']);
    6}

    This way, you can easily default it, you know the files that will be included and you leave nothing up to chance. And, if you wanted to, you could name the names of the actual files different to prevent direct access.

Posted by k1rha
2012. 8. 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. 8. 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. 8. 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. 8. 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. 8. 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. 8. 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
2012. 8. 13. 14:04

#include<iostream>

using namespace std;

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

//주제 5. 참조 변수 이야기

//1. 개념 : 기존 메모리의 별명 

//2. 

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

int main(){


int n=10; //메모리 할당

int *p = &n; 

int &r = n;


r = 20;

cout << n << endl;


//int &r2; // error 반드시 초기값이 필요하다. 

int *& pr = p;  //포린터의 별명  오~케이

//int &* rp = &r; //error 별명의 주소 번지  에러에러 

int (&f)() = main; //함수의 별명 

int & r3 = 10;  //에러 참조변수를 강제로 지정해줄수는 없다.

const int & r4=10; // 상수는 상수에 넣을수 있다.

//int && r5 = 10;// 상수를 참조하는 문법 C++ 2.0에 등장



}


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

#include<iostream>


using namespace std;


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

//참조변수와 함수 인자 이야기

//1. 어떤 함수가 인자의 값을 변경한다면 포인터나 참조 모두 좋지만 포인터가 가독성 측면에서는 좋다.

//2. 어떤 함수가 인자의 값을 변경하지 않는다면 

//(A) built in type : call by value 가 더 좋다. foo(int)  //

//(B) User Define Type  : call by reference 가 좋다. foo(const Data&)

//

//

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


/*

//어떤 코드가 더좋을까? 

void foo(int a){} //1

void foo(const int &a){} //2

*/


/*

void inc1(int n){++n;}

void inc2(int *p){++(*p);}

void inc3(int &r){++r;}


int main(){


int a = 1, b=1, c=1;

inc1(a); //실패  - call by value

inc2(&b); // 성공 - call by point 

inc3(c); //성공 call  by reference 



cout << a << endl;

cout << b << endl;

cout << c << endl;


}*/

struct Data{

int data;

};


void foo(const Data & x) // call by value 는 인자값을 변경하지 않을것이라는 약속이다.

{ //하지만 메모리 사용량이 2배가 된다. 

//되도록이면 const & 를 사용하자!

x=10;

}

int main(){


Data a = 0; 



int a =10;

foo(a); //이 함수는 절대 a 의 값을 변경하면 안된다.

cout << a<<endl; // a= 0이 나와야 한다.



}


==============================================================================================
#include<iostream>
using namespace std;
/////////////////////////////////////////////////////////////////////////////////////////
// 1. built in type ( int foo()) : 상수 리턴
// 2. User Define type(Point foo()): 임시객체 (상수는 아니다.)
// 
// 함수가 참조로 리턴하는 이유 
// 1. built in type(int &foo()) : 함수 호출을 l value 에 놓고 싶다. foo() = 20
//
// 2. User Define Type( Point & foo()) : 임시 객체를 만들지 말라는 의미!!
//
///////////////////////////////////////////////////////////////////////////////////////////

struct Point{
int x;
int y;
};

Point p = {1,2};
/*
Point foo(){

return p;

}
*/
Point & foo(){
return p;
}

int main(){


foo().x = 10;  //구조체 자체를 리턴하기떄문에 가능하다.
cout << p.x << endl; // 하지만 10 이 나오진 않는다.  1이 나온다. why?!
//복사생성자를 통해서 구조체를 리턴하기 떄문이다.  즉 foo().x 는 임시객체에 들어가게 된다.
//왜냐하면 임시객체가 없으면 지역변수 구조체를 리턴할 수 없다. 
//이를 해결하기 위해서는 Point foo()를 아래와 같이 수정한다.
//


}

Posted by k1rha