2010-05-21 1 views
3

우리는 클래스에 MyClass와 memberfunc()가 있다고 가정 해 보겠습니다. 이 MyClass에 대한 객체가 생성됩니다 (ObjA).멤버 func은 프로그래밍 방식으로 *이를 호출하는 '객체의 이름'을 알 수 있습니까?

i.e MyClass ObjA; 

ObjA는 memberfunc()를 호출합니다.

memberfunc() 안에 'ObjA'라는 이름을 프로그램 적으로 가져올 수 있습니까?

참고 : RTTI (런타임 유형 식별)를 사용하여 'MyClass'와 같은 객체 유형을 얻는 방법을 알고 있습니다. 아래의 radman에서도 마찬가지입니다.

편집 :이, C++로 가능하지 않다가 다른 프로그래밍 언어로 가능한 경우

? 몇 가지 해석 할 수 없습니다로

EDIT2

는 질문에 약간의 수정을했다.

+0

http://www.aspectc.org/fileadmin/documentation/ac-quickref.pdf을 : 여기 내 말은 무엇 const 정적의 char * 서명을() 는 조인 포인트 (함수 이름의 텍스트 설명을 제공합니다 , 클래스 이름, ...)? –

+1

* *에 대해이 이름 *을 원하십니까? 문제를 해결할 수있는 해결책이있을 수 있습니다. –

+0

@Anton : 어떤 프로덕션 코드에서도 이것을 원하지 않습니다. 그러나 어떤 개념을 가르치는 동안, 이것이 있다면 거기에 도움이 될 수 있기를 바랍니다. 어쨌든이 점을 높이 줘서 고마워. – AKN

답변

8

여기에 몇 가지 문제가 있습니다

  1. 객체 아무것도 호출하지 않는 코드는 않습니다.
  2. 개체에는 이름이 없습니다. 객체는 대개 변수에 할당되며, 종종 하나 이상의 변수에 할당됩니다. 배열 요소와 같이 변수가 전혀없는 경우가 있습니다.
  3. 호출 스택에 액세스하기 은 호출 한 코드를 소유하고있는 호출 클래스에 대해 약간의 아이디어를 제공하지만, 대부분의 언어의 리플렉션 기능을 뛰어 넘는 수준의 내성이 필요합니다.
    • 파이썬은 주목할만한 예외입니다. 그것은 걷고 많은 흥미로운 것들을 파악 스택을 줄 수 있습니다. C++은 그렇지 않습니다.

내가 코드를 같은 물건을 알아낼 수있는 능력을 제공하여 (이 방법에 의해 매우 비 이식) 스택을 열고 균열 C++ 라이브러리를 보았다, "누가 내게 전화를?" 그러나 나는 그 재료를 수년간 사용하지 않았습니다.

+0

+1하지만 배열 요소는 * 변수가 아니라 익명의 객체 일 수도 있습니다 – fredoverflow

+0

어떤 의미에서 객체는 이름을 가지고 있습니다. 주소입니다. 원래의 질문자가 염두에 두었던 이름이 아닙니다. –

+0

Java의 log4j는 클래스와 줄 # 로그 문을 알려줍니다. 비슷한 언어를 사용할 수있는 로깅 프레임 워크를 사용하는 다른 언어. log4j는 예외를 throw하여 catch하고 스택 추적 (또는 유사한 메서드)을 구문 분석하여이를 수행한다고 생각합니다. (With 염두에두고, 나는 파이썬이 '주목할만한 예외'는 아니라고 생각할 것이다.) 또한 Perl의 Data :: Dumper :: Simple은 Dumper 메소드에 전달 된 변수의 이름을 알려줍니다. – harschware

3

아니요, 방법이 없습니다. C++에는 반사가 없습니다. 일 수 있습니다. 제 2의 생각에서, 예를 들어, Java에는이 기능이 없습니다.

C++는 소스 코드의 식별자를 더 이상 포함하지 않는 기계어 코드로 직접 컴파일됩니다. 물론 개체 필드에 "변수 이름"을 저장할 수 있습니다 (개체가 단일 이름으로 참조되는 경우 ...).

+0

리플렉션이 실제로 여기서 도움이 될 수 있다고 생각하지 않습니다 ... 리플렉션은 객체의 유형에 대한 정보를 제공하지만 특정 인스턴스 'objA'는 제공하지 않습니다. –

+0

확인. RTTI (Real Time Type Identification)에 대해 C++로 말씀 하시길 바랍니다. – AKN

+0

@David, 당신 말이 맞아요, 당신이이 코멘트를 쓰는 동안 방금 내 게시물을 업데이트했습니다 :-) –

3

아니요, 객체 이름은 소스 코드에만 존재합니다. 일단 컴파일되면 객체 참조는 메모리 오프셋뿐입니다. 변수 이름을 알고 싶다면 어딘가에서 문자열을 설명해야합니다.

내성 메커니즘 (예 : Reflection)이있는 언어로 변수 이름을 가져 오는 기능은 제한적이며 널리 사용 가능하지 않습니다. 변수 이름을 얻으려면 C#의 경우에도 투영이라는 기발한 C# 3.5 기능을 사용해야하고 추출을 위해 농구를 뛰어 넘어야합니다. 그렇다면 코드를 프로그래밍해야합니다. 코드의 어느 시점에서나 사용할 수있는 것은 아닙니다.

회원 함수에서 객체의 이름을 가져 오는 중 일부 질문을 생각한 후에는 이론적으로는이 불가능합니다. 우리는 두 변수가 가리키는으로 ObjA의 한 인스턴스가 (내가 용어 오히려 느슨하게 여기를 가리키는 사용)

class ObjA { 
public: 
    void memberfunc() { 
    //confused??? instance1 or instance2? 
    } 
}; 

//main 
ObjA instance1; 
ObjA* instance2 = &instance1; 
instance2->memberfunc(); 

위의 예에서이 시나리오를 생각해 보자. 이러한 변수는 개체의 제어권 밖에서 완전히 벗어날 수 있으므로 변수 이름을 가져 오는 기능을 사용할 수있는 경우에도 해당 변수를 가져올 수 없습니다.

C#에서는 익명 클래스와 Reflection을 사용하여 변수 이름을 얻을 수 있습니다. 그렇게하는 방법은 상당히 어색하며 누군가에게 뭔가를 보여주기 위해 이것을 사용하려는 경우 지금 당장 포기해야합니다. 왜냐하면 두 가지 모두 혼란 스러울 것이기 때문입니다. 이 기술은 주류 프로그래밍에 익숙하지 않은 익명의 클래스, 프로젝션, 확장 메소드 및 리플렉션을 포함하는 몇 가지 기능을 사용합니다.

public static class Extensions { 
    public static string GetFirstPropertyName(this object obj) { 
    return obj.GetType().GetProperties()[0].Name; 
    } 
} 

public class Program { 
    public static void Main() { 
    int intVal = 5; 
    var name = (new {intVal}).GetFirstPropertyName(); 
    //name=="intVal" 
    } 
} 
+2

Real 남자들은 기계 코드로 된 프로그램을 7 홀 테이프에 직접 펀치. –

+0

테이프? 겁쟁이들만이 테이프를 사용합니다. 와이어를 움직이지 않는다면 실제 프로그래밍을하지는 않을 것입니다! –

0

글쎄, 당신의 질문이 약간 불분명 한 것처럼 보일지 모르겠지만, 그 중 하나에서 클래스의 이름을 인쇄하고 싶다고 가정하면, 꽤 가능합니다.

typeid 명령을 사용해야합니다. 이것은 런타임에 클래스 유형의 객체에 대한 사람이 읽을 수있는 이름에 가까운 것을 추출합니다. 플랫폼은 당신이 얻을 이름이 플랫폼에서 내가 예제 코드는 아래 '4ObjA'이었다에서 가져온 어떤 플랫폼 (따라 다를 수 있습니다 즉 걸쳐 그러나 당신은 일관되고이 이름에 의존 할 수 없다.

#include <iostream> 
#include <typeinfo> 
class ObjA 
{ 
public: 
    void memberfunc() 
    { 
    std::cout << typeid(*this).name() << std::endl; 

    } 
}; 

int main(int argc, char **argv) 
{ 
    ObjA obj; 
    obj.memberfunc(); 

} 
0

귀하의 질문은하지 않습니다 완전히 지우기 - 메서드가 속한 개체 또는 멤버 함수를 호출하는 메서드의 이름을 알고 싶습니까? 아니면 다른 무엇입니까?

대부분의 개체 지향 언어에서 다음과 같은 이름을 사용할 수 있습니다. 현재 클래스는 꽤 ​​쉽게 :

class Myclass(object): 
    def memberfunc(self): 
     print self.__class__.__name__ 

obja = Myclass() 
obja.memberfunc() # prints Myclass 

bly는 거의 모든 언어로 이름으로 obja 식별자를 얻습니다. 왜 그런지 알고 싶지 않습니다 (어떤 키/값 매핑을 사용합니다)

import inspect 

class Myclass(object): 
    def memberfunc(self): 
     current_call = inspect.stack()[0] 
     previous = inspect.stack()[1] 
     print previous[3] 

def somefunc(): 
    obja = Myclass() 
    obja.memberfunc() # prints somefunc 

somefunc() 

나는이 다른 언어

을 같이 쉽지 않다 상상 : 메소드를 호출 된 메소드의 이름을 얻으려면, 당신은 inspect 방법을 사용하여 파이썬에서 예 호출 스택을 검사해야

다시 한 번 그런 일을하고 싶은 경우는 드뭅니다. 보통 코드 커버 리아와 같은 내성이 강한 것 도구 및 디버거

+0

'멤버 함수를 호출하는 메서드의 이름'을 묻는 중이었고 올바르게 대답했습니다. 감사. – AKN

0

다른 게시물에서 다루었으므로 런타임에 코드에서 선택하는 변수 이름 식별자에 직접 액세스 할 수있는 방법이 없습니다. 시스템 관점에서 볼 때 변수 이름 식별자에 액세스 할 필요가 없습니다.

class Foo 
    def foo 
     puts self.class 
    end 
end 

class Bar < Foo 
end 

f = Foo.new 
b = Bar.new 

f.foo #=> Foo 
b.foo #=> Bar 

당신은 typeid와 C++과 유사 할 수 있지만, 정확한되지 않습니다 : 그러나 루비는 구조의 측면에서 발신자의 세부 사항에서 얻을 간단하다. 예를 들어,

#include <iostream> 
class Foo { 
    public: 
     void foo() { std::cout << typeid(this).name() << std::endl; } 
}; 

int main() { 
    Foo f; 
    f.foo(); // on my system returns P3Foo 
    return 0; 
} 
0

이것은 일종의 해킹이지만 매크로를 사용하여 클래스 식별자 이름을 저장할 수 있습니다.

#include <iostream> 
#include <string> 

#define createMyClass(x) MyClass x("x") 

class MyClass{ 
    string _name; 
    MyClass(const string& name) : _name(name){} 
    memberfunc(){ 
     std::cout << "Name: " << _name << std::endl; 
    } 
} 

int main (int argc, char **argv) { 
    createMyClass(ObjA); 
    ObjA.memberfunc(); // prints the name 
    return 0; 
} 
관련 문제