~cpp #include <iostream> using namespace std; class Foo{ public: int id; Foo(){ static idSequance = 0; id = idSequance++; cout << "Create! id = " << id << endl; } void die(){ cout << "I suicide. Id is " << id << endl; delete this; // 자신 삭제 } void sayMyId(){ cout << "My Id is no " << id << endl; } void sayHello(){ cout << "say Hello" << endl; } }; int main(int argc, char** argv) { cout << endl << ":::::: Case 1 - 동적할당 " << endl; Foo* foo1 = new Foo();// Create! 를 출력한다. foo1->sayHello(); // Hello 출력 foo1->sayMyId(); // id 출력 foo1->die(); // 객체 삭제 foo1->sayHello(); // 동작 가능 foo1->sayMyId(); // 동작 가능 // id 확인차 cout << endl << ":::::: Case 2 - id 확인" << endl; Foo* foo2 = new Foo();// Create! 를 출력한다. foo2->sayHello(); // Hello World 출력 foo2->sayMyId(); // id 출력 foo2->die(); foo2->sayHello(); foo2->sayMyId(); cout << endl << ":::::: Case 3 - 포인터 NULL로 하고 메소드 호출하기 " << endl; Foo* foo3 = NULL; // 자세한 설명보세요. foo3->sayHello(); // Hello 를 출력한다. //foo3->sayMyId(); // debug, release 모두 동작할 수 없다. //foo3->die(); // debug, release 모두 동작할 수 없다. cout << endl << ":::::: Case3 - 지역변수로 선언" << endl; Foo foo4; foo4.sayHello(); // Hello World 출력 foo4.sayMyId(); // id 출력 foo4.die(); // debug mode에서 assertion error foo4.sayHello(); // release 에서 동작 가능 foo4.sayMyId(); // release 에서 동작 가능 cout << endl; return 0; }결과는 다음과 같이 출력됩니다. 비교해보면서, 생각해 보고 이해가지 않는다면 자세한 설명을 보세요.
~cpp :::::: Case 1 - 동적할당 Create! id = 0 say Hello My Id is no 0 I suicide. Id is 0 say Hello My Id is no 3604872 :::::: Case 2 - id 확인 Create! id = 1 say Hello My Id is no 1 I suicide. Id is 1 say Hello My Id is no 3604872 :::::: Case 3 - 포인터 NULL로 하고 메소드 호출하기 say Hello :::::: Case3 - 지역변수로 선언 Create! id = 2 say Hello My Id is no 2 I suicide. Id is 2 say Hello My Id is no 2 Press any key to continue
~cpp Foo* foo1 = new Foo(); // Create! 를 출력한다. foo1->sayHello(); // Hello World 출력 foo1->sayMyId(); // id 출력 foo1->die(); // 죽였다. foo1->sayHello(); // 호출이 된다? foo1->sayMyId(); // 이것도..--;
~cpp Foo* foo2 = NULL; // 자세한 설명보세요. foo2->sayHello(); // Hello 를 출력한다.(음--;) foo2->sayMyId(); // debug, release 모두 동작할 수 없다. foo2->die(); // debug, release 모두 동작할 수 없다.
~cpp class Foo{ public: int id; // <- 이 부분의 정보 입니다. };C++은 Strong typed language 이므로 컴파일 시간에 모든 형이 선언되고, 사용되는 것을 검증할 수 있습니다. 하지만 이는 다음과 같은 지역 변수에 국한합니다.
~cpp Foo foo4;new 키워드로 할당시에는 runtime 에 class 의 instance 를 찍어 낼수 있어야 합니다. 이를 위해 프로그램 안에는 위의 id가 int 라는 정보를 담는 class의 "class 틀" 정보를 담는 곳이 필요합니다.
~cpp class Foo{ public: int id; void sayMyId(){ cout << "My Id is no " << id << endl; } };라는 함수는 각 instance의 id 라는 인자에 접근합니다.
~cpp Foo::sayMyId()
같은 아무런 인자 없는 함수의 실행코드가 함수 선언 영역에 세팅된다면, id 라는 인자에 접근할수 없습니다. ~cpp Foo:sayMyId()라는 함수 실행 코드가 함수 영역에 선언될때 컴파일러가
~cpp Foo:sayMyId(Foo* x)라는 형태의 함수로 선언하고, 실행할수 있도록 만듭니다. 그리고, 호출한다면
~cpp Foo*
부분에 ~cpp foo1->sayMyId(foo1);형태로 함수 포인터를 세팅해서 함수 코드를 실행합니다.
~cpp Foo* foo1 = new Foo(); // Create! 를 출력한다. foo1->sayHello(); // Hello 출력 foo1->sayMyId(); // id 출력 foo1->die(); // 객체 삭제 foo1->sayHello(); // 동작 가능 foo1->sayMyId(); // 동작 가능
~cpp Create! id = 0 say Hello My Id is no 0 I suicide. Id is 0 say Hello // 객체 삭제(delete this)후 실행 코드 My Id is no 3604872 // 객체 삭제(delete this)후 실행 코드
~cpp sayHello() 와 sayMyId()
일겁니다. 둘째 설명의 member 함수를 호출하는 메커니즘을 이해했다면 ~cpp sayHello() -> sayHello(Foo*) sayMyId() -> sayMyId(Foo*)형태로 호출된다는 것을 짐작할 수 있을 겁니다. 하지만 두 함수는 다른 점이 있습니다.
~cpp sayMyId()
는 접근한다는 점이지요.~cpp say Hello 객체 삭제(delete this)후 실행 코드 My Id is no 3604872 객체 삭제(delete this)후 실행 코드instance에 사용되었던 메모리는, 해당 process의 가용 메모리로 돌아가지, 접근 금지 영역으로 세팅되지 않습니다. 이 부분은 delete this 시 해당 instance 영역의 값을 어떻게 "청소"하느냐에 따라서, 플랫폼 별로 다르게 나옵니다.
~cpp delete x라는 코드는 x의 값을 변화시키지 않습니다. 변화시킬수 없습니다. 이유는 call by value 로 넘어온 x의 값을 NULL로 변경시켜봤자, 영향 받지 않는 코드가 경우가 있기 때문에, 변화시킬 필요성이 없습니다.
~cpp Foo* foo2 = NULL; // 자세한 설명보세요. foo2->sayHello(); // Hello 를 출력한다.이 코드의 결과는
~cpp say Hello과 같이 잘 동작합니다. 호출 형태가
~cpp Foo::sayHello(foo2) -> Foo::sayHello(NULL)이 된것이고, sayHello 내에는 pointer 값 NULL 을 이용한 접근이 없으므로 아무런 에러가 발생하지 않습니다.
~cpp // Main.java file class Foo{ public int a; void sayHello(){ System.out.println("Hello"); } } public class Main { public static void main(String[] args) { Foo foo= null; foo.sayHello(); } }이를 실행하면, 다음과 같은 exception을 출력합니다. 이는 Java Language Specification 2nd(http://java.sun.com/docs/books/jls/second_edition/html/j.title.doc.html) (3rd가 아직 안나왔군요.) 와 jvm specification(http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html)을 참고하세요.
~cpp java.lang.NullPointerException at Main.main(Main.java:19) Exception in thread "main"