2014-01-06 5 views
-1

클래스의 메서드에 대한 포인터를 제거하는 다음 샘플 C++ 프로그램이 있습니다. 해당 메서드를 호출 할 때 컴파일러 오류가 발생합니다.C++ 메서드 포인터 호출

10  class Foo 
11  { 
12   void set_parm1(string) {} 
13   void set_parm2(string) {} 
14 
15   typedef void (Foo::*set_func_t)(string); 
16   struct Bar 
17   { 
18    string value; 
19    set_func_t set_func; 
20   }; 
21 
22   map<string, Bar> parameter; 
23 
24   public: 
25   Foo(); 
26   void set_value(string key, string value); 
27  }; 
28 
29  Foo::Foo() 
30  { 
31   Bar temp; 
32 
33   temp.value = "value1"; 
34   temp.set_func = &Foo::set_parm1; 
35   parameter["param1"] = temp; 
36 
37   temp.value = "value2"; 
38   temp.set_func = &Foo::set_parm2; 
39   parameter["param1"] = temp; 
40  } 
41 
42  void 
43  Foo::set_value(string key, string value) 
44  { 
45   Bar temp; 
46 
47   temp = parameter[key]; 
48   this->*temp.set_func(value); 
49  } 

질문 : 라인에서

  1. 컴파일러 오류가 48

    ./test.cc: In member function 'void Foo::set_value(std::string, std::string)' : ./test.cc:51:35: error: must use '.*' or '->*' to call pointer-to-member function in 'temp.Foo::Bar::set_func (...)' , e.g. '(... ->* temp.Foo::Bar::set_func) (...)'

  2. 나는지도에 parmX의 값을 업데이트 할 set_func()을 (set_parm1() 또는 set_parm2() 중 하나를 가리키는) 원하는 그 자체. 그것은 내가 (라인 33)의 addr을 얻을 수 있습니까? set_func()에 전달할 수 있도록 map 매개 변수에 저장되어 있습니까?

    아니요, 그렇다면 다음 옵션은 바의 복사본이 아니라 맵의 "바"에 대한 포인터를 저장하십시오. 기본적으로 map<string, Bar *>을 사용하십시오.

  3. STL (부스트 라이브러리 사용하지 않음)을 고수하면 ptr을 구조체/클래스에 저장하고지도에 전체 개체를 저장하는 지침이 있습니까? (물론 이것은 struct/class가 포인터를 가지고 있지 않다고 가정합니다. 전체 객체를 저장할 때 딥 카피는 필요 없습니다.)


아메드을 주셔서 감사합니다. 경우 1

+1

뭘 그냥 표준 : 기능과 표준 : : 바인드를 사용하지 마십시오

은 예를 들어 (귀하의 질문에 코드를 기반으로)? – PlasmaHH

+0

라인 48 : * – ipinak

+1

@ipinak을 제거하고'this->'를 제거 하시겠습니까? –

답변

3

: 당신은 (? 당신은 아마 Bar.value 의미) temp.value의 주소를 취할 수 있지만, 그대로 그 쓸모없는 것 : 2의

(this->*temp.set_func)(value); 

: 당신은 괄호에 넣어 필요 임시 변수이므로 Foo 님의 ctor 완료 후 주소가 유효하지 않습니다.

3 : 나는 당신이 무슨 뜻인지 정말로 모르겠다. std::shared_ptr 등을 사용할 수 있습니다. al. 당신이 오버 헤드를 줄이기 위해 크고 값 비싼 객체 또는 이동 의미와 같은 다른 수단의 복사를 피하고자하지만 일반적인 대답이 없다면 나는 두려워합니다.

2

@ Daniel Frey가 제안한 해결책이 효과적 일 수 있습니다.

그러나 C++ (또는 그와 관련하여 다른 객체 지향 언어)에서 수행하는 올바른 방법은 다형성입니다.

기술적 측면에서 함수 포인터 대신 가상 함수와 결합 된 상속을 사용하는 것이 좋습니다.

class Foo 
{ 
protected: 
    virtual void set_parm(string)=0; 
    struct Bar 
    { 
     string value; 
    }; 
    map<string, Bar> parameter; 
public: 
    void set_value(string key, string value); 
}; 

class Foo1 : public Foo 
{ 
private: 
    void set_parm(string) {} // you probably wanna do something here... 
public: 
    Foo1(); 
}; 

class Foo2 : public Foo 
{ 
private: 
    void set_parm(string) {} // you probably wanna do something here... 
public: 
    Foo2(); 
}; 

void Foo::set_value(string key, string value) 
{ 
    Bar temp; 
    temp = parameter[key]; 
    set_parm(value); 
} 

Foo1::Foo1() 
{ 
    Bar temp; 
    temp.value = "value1"; 
    parameter["param1"] = temp; 
} 

Foo2::Foo2() 
{ 
    Bar temp; 
    temp.value = "value2"; 
    parameter["param1"] = temp; 
} 
+0

+1 참고 컴파일 문제 만 해결 했으니 친절하게 처리 한 디자인 문제가 아닙니다. 따라서 upvote :) –