문제

내 응용 프로그램에서 이와 유사한 코드가 있습니다.

class A
{
  public: int b;
}

class C
{
  public: int d;
}

void DoThings (void *arg1, MYSTERYTYPE arg2);

A obj_a;
C obj_c;

DoThings(&obj_a, &A::b);
DoThings(&obj_c, &C::d);

문제는 - 미스터리 유형은 무엇입니까? void* 또는 int 작동은 값에도 불구하고 인쇄 된 경우 인쇄 된 경우에도 잘 인쇄됩니다.

설명 : 예, & A :: B는 C ++에 따라 정의됩니다. 예, 나는 클래스 멤버에게 오프셋을 얻으려고 노력하고 있습니다. 예, 나는 까다 롭습니다.

편집 : 오, 오프셋 ()를 사용할 수 있습니다. 어쨌든 감사합니다.

도움이 되었습니까?

해결책

두 개의 관련없는 클래스에 대한 데이터 멤버 포인터가 있습니다. 글쎄, 당신은 두 포인터를 모두 잡을 수있는 일반적인 유형을 찾을 수 없습니다. 함수 매개 변수가 파생의 멤버에 대한 데이터 멤버 포인터 인 경우에만 작동합니다.베이스에 포함 된 경우 멤버도 포함 할 수 있기 때문입니다.

struct a { int c; }; struct b : a { }; int main() { int b::*d = &a::c; }

업데이트: 위의 변환이 왜 a::* 에게 b::* 암시 적으로. 결국, 우리는 보통 가지고 있습니다 b* 에게 a* ! 고려하다:

struct a { };
struct b : a { int c; };
struct e : a { };
int main() { int a::*d = &b::c; e e_; (e_.*d) = 10; /* oops! */ }

위의 유효가 있으면 실제로 많이 망칠 것입니다. 위의 것입니다 ~ 아니다 전환하기 때문에 유효합니다 b::* 에게 a::* 암시 적이 아닙니다. 보시다시피, 우리는 B :: C에 포인터를 할당 한 다음 전혀 포함하지 않는 클래스를 사용하여 피할 수있었습니다! (e). 컴파일러는이 순서를 시행합니다.

int main() { int b::*d = &b::c; e e_; (e_.*d) = 10; /* bug! */ }

그것 실패합니다 왜냐하면 지금 컴파일하기 때문입니다 e 파생되지 않습니다 b, 멤버 포인터 포인터가 속한 클래스. 좋은! 그러나 다음은 매우 유효하며 물론 컴파일됩니다 (변경된 클래스 a 그리고 b):

struct a { int c; };
struct b : a { };
struct e : a { };
int main() { int e::*d = &a::c; e e_; (e_.*d) = 10; /* works! */ }

케이스에서 작동하려면 기능을 템플릿으로 만들어야합니다.

template<typename Class>
void DoThings (int Class::*arg) { /* do something with arg... */ }

이제 컴파일러는 주어진 멤버 포인터가 속한 올바른 클래스를 자동으로 배치합니다. 실제로 사용하려면 멤버 포인터와 함께 인스턴스를 전달해야합니다.

template<typename Class>
void DoThings (Class & t, int Class::*arg) { 
    /* do something with arg... */ 
    (t.*arg) = 10;
}

Dothings를 작성할 때 이미 알고있는 멤버를 설정하려면 다음과 같습니다.

template<typename Class>
void DoThings (Class & t) {  
    t.c = 10;
}

다른 팁

당신은 단순히 내부에 사는 정수의 주소로 함수를 호출하려고합니까? A 또는 a C 물체? 이 경우 Jeff McGlynn의 대답은 갈 길입니다.

그렇지 않으면, C ++의 이상한 포인터 투 선원 시설을 요구하는 까다로운 일을하려고한다면 (거의 확실하지 않습니다).

수업 이후 A 그리고 C 관련이 없으므로 두 가지 모두 처리하려면 템플릿 기능이 필요합니다.

template <typename T>
void DoThings(int T::*x);

만약에 C 실제로 파생되었습니다 A, 다음은 작동합니다.

void DoThings(int A::*x);

& a :: b 및 & c :: d는 무의미하며 관련 주소는 없습니다. 회원의 오프셋을 얻으려고합니까?

다음과 같은 것을 원하지 않습니까?

DoSomething(&obj_a,&obj_a.b);

j_random_hacker가 제안한대로 템플릿을 사용하고 컴파일러가 기능을 호출하는 지점에서 각 클래스의 유형을 알고 있다면 질문에 대한 문자 그대로의 대답은 "입니다."template <typename CLASS> void DoThings (CLASS * object, int CLASS::*MEMBER)".

예제에 맞는 방법은 다음과 같습니다.

#include <iostream>

class A {
public: 
    int b;
};

class C {
public: 
    int d;
};

template <typename CLASS>
void DoThings (CLASS * object, int CLASS::*MEMBER)
{
    std::cout << object->*MEMBER << std::endl;
}

A obj_a = { 2 };
C obj_c = { 4 };

int main (int argc, const char * argv[])
{
    DoThings(&obj_a, &A::b);
    DoThings(&obj_c, &C::d);
    return 0;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top