파이썬은 다른 많은 언어와는 달리 변수의 이름과 값 객체가 분리되어 있다. 예를 들어, a = 1 이란 문에서 숫자 1이 변수 a에 저장되는 것이 아니다. 

파이썬에서는 a를 이름, 숫자 1을 객체라고 하며, 두 개념은 분리되어 있다.


그림으로 표현하면 이렇다. 

(이름 a)  -----------------> (객체 1)

즉, 이름 a는 객체 1을 가리킨다. 객체1은 별도의 위치에 존재하고 있는 것이다.


※ 일반적인 컴파일러 언어(소스 코드를 기계어 수준으로 번역해서 실행하는 언어. C언어가 대표적이다.) 는 이름과 객체의 개념이 분리되어 있지 않다. 컴파일러 언어에서의 이름은 번역될 때 실제 메모리 주소로 모두 변환되므로 프로그램을 수행하는 런타임 시점에서는 이러한 심볼의 이름들은 의미가 없다. 

즉, 변수 혹은 객체의 이름은 해당 객체의 주소로 변환된다.


이에 반해서 파이썬과 같은 동적인 자료형을 가지는 언어에서는(대부분의 스크립트 언어) 변수의 생성과 소멸이 언제든지 일어날 수 있기 때문에 이름이 주소로 변환되지 않고 별도의 장소에 이름이 보관된다.

그리고, 이름과 객체와의 관계 정보를 추가로 가지고 있다. 이름이 저장되는 장소를 '심볼 테이블(Symbol Table)' 이라고 한다.



객체의 치환



간단한 테스트를 통해 a의 값을 바꿔서 b,c의 값이 바뀌는지를 확인하면,

공유객체인지 아니면 분리된 객체인지 (참조로 되는지, 복사로 되는지를) 확인할 수 있다.


a[1]의 값만을 변경했는데 b와 c가 같이 변했다. 이 결과는 객체가 공유된다는 뜻이다. 

사실 이름 a는 객체의 레퍼런스를 나타내는 것이므로 b와 c는 동일 객체의 레퍼런스만 저장하고 있는 것이다. 


※ 일반적으로 python에서의 치환은 대부분 레퍼런스에 의해 이루어진다.

만일 객체의 복사를 원한다면 객체에 따른 방법을 적용하거나 일괄적으로 copy 모듈을 이용하면 된다.




python에서 일반적인 변수가 C언어의 pointer 변수와 똑같구나..!!

'Programming > Python' 카테고리의 다른 글

자료형의 종류  (0) 2012.11.25
문자열로 된 파이썬 코드 실행  (0) 2012.11.22
파이썬의 keyword  (0) 2012.11.21
파이썬 환경 변수 설정  (0) 2012.11.21
리눅스에서 스크립트 실행하기  (0) 2012.11.21
Posted by scii
:

객체 내에 멤버함수는 실제로 객체 내에 존재하지않는다.

하지만, 진실을 알고 난 이후에도 객체 내에 멤버함수가 존재한다고 인식하고 객체를 바라봐야 한다. 개념적으로는, 그리고 객체지향적 논리를 기준으로는, 객체 내에 멤버함수가 존재한다고 인식하는 게 옳으니 말이다. 



C언어 스타일의 구조체와 전역함수를 이용하여 흉내낸 C++객체의 예))



핵심은 두 개의 구조체 변수(객체)가 함수를 공유하고 있다는 사실이다. 

그리고 실제로 C++의 객체와 멤버함수는 이러한 관계를 갖는다.

즉, 객체가 생성되면 멤버변수는 객체 내에 존재하지만, 멤버함수는 메모리의 한 공간에 별도로 위치하고선, 이 함수가 정의된 클래스의 모든 객체가 이를 공유하는 형태를 취한다. 

그리고 객체가 지니고 있는 멤버변수 대상의 연산이 진행되도록 함수를 호출하는 것이다. 

Posted by scii
:

객체 배열


: 객체 배열 및 객체 포인터 배열은 C언어의 구조체 배열과 구조체 포이터 배열과 유사하다.


객체 기반의 배열은 다음의 형태로 선언한다(Simple이 클래스 이름).

Simple arr[10];


이를 동적으로 할당하는 경우에는 다음의 형태로 선언한다.

Simple * ptrArr = new Simple[10];


이러한 형태로 배열을 선언하면, 열 개의 Simple 객체가 모여서 배열을 구성하는 형태가 된다. 이렇듯 구조체 배열의 선언과 차이가 없다.

하지만 배열을 선언하는 경우에도 생성자는 호출이 된다. 단, 배열의 선언과정에서는 호출할 생성자를 별도로 명시하지 못한다(생성자에 인자를 전달하지 못한다). 즉, 위의 형태로 배열이 생성되려면 다음 형태의 생성자가 반드시 정의되어 있어야 한다.

Simple(void) {...}


그리고 배열 선언 이후에 각각의 요소를 원하는 값으로 초기화시키길 원한다면, 일일이 초기화의 과정을 별도로 거쳐야 한다.



객체 배열의 예제

#include <iostream>

#include <cstring>

using namespace std;


class Person

{

private:

char * name;

int age;


public:

Person(char* myname, int myage)             //생성자

:age(myage)

{

int len = strlen(myname);

name = new char[len];

strcpy(name, myname);

}

Person() //생성자. 배열 생성시 필요한 생성자를 추가하였다.

{

name = NULL;

age = 0;

cout<<"called Person()"<<endl;

}

void SetPersonInfo(char * myname, int myage)

{

name = myname;

age = myage;

}

void ShowPersonInfo() const

{

cout<<"이름: "<<name<<", "<<"나이: "<<age<<endl;

}

~Person() //소멸자

{

delete []name;

cout<<"called Destructor!"<<endl;

}

};


int main(void)

{

Person pArr[3];             //class Person 3개를 가지고있는 배열.

char nameStr[100];

char * strPtr;

int age;

int len;


for(int i=0; i<3; i++)

{

cout<<"이름: ";

cin>>nameStr;

cout<<"나이: ";

cin>>age;

len = strlen(nameStr)+1;

strPtr = new char[len];

strcpy(strPtr, nameStr);

pArr[i].SetPersonInfo(strPtr, age);

}


for(int i=0; i<3; i++)

pArr[i].ShowPersonInfo();


return 0;

}


실행결과




객체 배열 생성시 void형 생성자가 호출됨을 확인할 수 있다. 그리고 배열 소멸시에도 그 배열을 구성하는 객체의 소멸자가 호출됨을 확인할 수 있다.


-----------------------------------------------------------------------------------


객체 포인터 배열


: 객체 배열이 객체로 이뤄진 배열이라면, 객체 포인터 배열은 객체의 주소 값 저장이 가능한 포인터 변수로 이뤄진 배열이다.


#include <iostream>

#include <cstring>

using namespace std;


class Person

{

private:

char * name;

int age;


public:

Person(char* myname, int myage)             //생성자

:age(myage)

{

int len = strlen(myname)+1;

name = new char[len];

strcpy(name, myname);

}

void ShowPersonInfo() const

{

cout<<"이름: "<<name<<", "<<"나이: "<<age<<endl;

}

~Person() //소멸자

{

delete []name;

cout<<"called Destructor!"<<endl;

}

};


int main(void)

{

Person* pArr[3];                 //class Person 가리킬 수 있는 객체 포인트 배열.

char nameStr[100];

int age;


for(int i=0; i<3; i++)

{

cout<<"이름: ";

cin>>nameStr;

cout<<"나이: ";

cin>>age;

pArr[i] = new Person(nameStr, age);    //객체를 생성해서, 이 객체의 주소 값을 배열에 저장하고 있다.

}


for(int i=0; i<3; i++)

{

pArr[i]->ShowPersonInfo();

delete pArr[i]; //new연산을 진행하였으니 delete연산 진행.

}


return 0;

}


실행결과




※ 객체를 저장할 때에는 위의 예제에서 보인 두 가지 방법 중 하나를 택해야 한다. 즉, 저장의 대상을 객체로 하느냐, 객체의 주소 값으로 하느냐를 결정해야 한다.


'Programming > C++' 카테고리의 다른 글

복사 생성자(Copy Constructor)  (0) 2012.05.22
this 포인터  (0) 2012.05.21
생성자 & 소멸자를 이용한 예제  (0) 2012.05.21
생성자를 이용한 예제.  (0) 2012.05.21
소멸자(Destructor)  (0) 2012.05.20
Posted by scii
: