2012-02-24 2 views
4

두 가지 소프트웨어 사이에서 어떤 종류의 브리지를 만들어야하지만 다루는 방법을 모르는 문제가 있습니다. 바라건대 누군가는 흥미롭고 (가능한) 작업 제안을 할 것입니다.C++ 클래스의 멤버를 처리해야하는 정적 함수

여기에 배경이 있습니다. 저는 C++ 소프트웨어 제품군을 보유하고 있습니다. 주어진 클래스 내의 일부 함수를 다른 함수로 대체해야하는데, 이는 괜찮습니다. 문제는 새 함수가 정적이어야하는 다른 함수를 호출하지만 클래스의 멤버를 처리해야한다는 것입니다. 이것은 저를 화나게 만드는 두 번째 기능입니다.

기능 나는 다음과 같은 오류가 정적이 아닌 경우 :

error: cannot call member function ‘void 
MyClass::MyFunction(const double *)’ without object 

또는

error: ‘this’ is unavailable for static member functions 
: 나도 다음과 같은 오류가

error: argument of type ‘void (MyClass::)(…)’ does not match ‘void (*)(…)’ 

내가 정적으로 설정하면

"this"키워드 ("Function()"또는 "this-> Function()"사용 여부에 따라 다름).

마지막으로 클래스 객체에는 정적 함수에 전달할 수없는 몇 가지 인수가 필요합니다 (정적 함수 프로토 타입을 수정할 수 없음). 정적 함수 자체 내에 새 인스턴스를 만들 수 없습니다.

최소한의 재 작성으로 어떻게 이러한 문제를 해결할 수 있습니까?

편집 : 좋아, 여기에 내가해야 할 일에 대한 간단한 예제가 명확하고 정확 희망입니다 : 비 정적 멤버 함수에

// This function is called by another class on an instance of MyClass 
MyClass::BigFunction() 
{ 

    … 
// Call of a function from an external piece of code, 
// which prototype I cannot change 
    XFunction(fcn, some more args); 
    … 

} 


// This function has to be static and I cannot change its prototype, 
// for it to be passed to XFunction. XFunction makes iterations on it 
// changing parameters (likelihood maximization) which do not appear 
// on this sample 
void MyClass::fcn(some args, typeN& result) 
{ 

// doesn't work because fcn is static 
    result = SomeComputation(); 

// doesn't work, for the same reason 
    result = this->SomeComputation(); 

// doesn't work either, because MyClass has many parameters 
// which have to be set 
    MyClass *tmp = new MyClass(); 
    result = tmp->SomeComputation(); 

} 
+2

정적 함수는 정적 (정적이 아닙니다) 멤버 변수에 액세스 할 수 없습니다. 처음이자 마지막 시도는 무엇인지 확실하지 않습니다. 관련 코드를 표시 할 수 있습니까? –

+0

코드를 알려주십시오. –

+0

정적 함수의 선언과 정의가 포함 된 코드를 게시하십시오. 그렇지 않으면 무엇이 요구되는지 이해하기 어렵습니다. 정적 함수에는'this' 포인터가 없으므로'this->'를 할 수 없습니다. 함수에 매개 변수로 작업해야하는 객체를 전달해야합니다. – Naveen

답변

1

초기 질문 아래 spencercw의 제안에 따라 나는 "this을 가리 키도록 설정된 정적 멤버 변수"솔루션을 시도했습니다 (글로벌 변수는 소프트웨어 제품군의 컨텍스트 내에서 까다 롭고 위험했을 것입니다).

그것은 않습니다
((MyClass*)currentObject)->SomeComputation(); 

로,

static void*   currentObject; 

그래서 난 그냥 그것을 사용 :

사실 내가 거기 알아 냈 이미 (내가 쓰지 않았다) 코드로 구현이 같은했다 일, 고마워요!

2

포인터를 처리하기 까다로운 조금이다. 가장 간단한 해결 방법은 함수에 불투명 포인터 인수를 추가 한 다음 'this'에 대한 포인터로 캐스팅 한 다음 필요로하는 것을 수행하는 것입니다.

void doSomething(int (*callback)(void *usrPtr), void *usrPtr) 
{ 
    // Do stuff... 
    int value = callback(usrPtr); 
    cout << value << "\n"; 
} 

class MyClass 
{ 
public: 
    void things() 
    { 
     value_ = 42; 
     doSomething(myCallback, this); 
    } 

private: 
    int value_; 

    static int myCallback(void *usrPtr) 
    { 
     MyClass *parent = static_cast<MyClass *>(usrPtr); 
     return parent->value_; 
    } 
}; 

int main() 
{ 
    MyClass object; 
    object.things(); 
    return 0; 
} 

이 예 myCallback()에서 불투명 포인터를 통해 민간 value_에 액세스 할 수 있습니다

여기 아주 간단한 예입니다.

당신은 더 C++하려는 경우 - 같은 접근 방식은 당신이 콜백으로 비 정적 멤버 함수를 전달할 수 Boost.Function을하고 Boost.Bind 사용으로 볼 수 있었다 :

void doSomething(boost::function<int()> callback) 
{ 
    // Do stuff... 
    int value = callback(); 
    cout << value << "\n"; 
} 

class MyClass 
{ 
public: 
    void things() 
    { 
     value_ = 42; 
     doSomething(boost::bind(&MyClass::myCallback, this)); 
    } 

private: 
    int value_; 

    int myCallback() 
    { 
     return value_; 
    } 
}; 

int main() 
{ 
    MyClass object; 
    object.things(); 
    return 0; 
} 

를 '당신이 정말로 수 있다면 전역 포인터를 사용할 수있는 함수 프로토 타입을 변경하지 마십시오. 그러나 클래스의 인스턴스가 둘 이상인 경우 모든 종류의 문제가 발생합니다. 그것은 일반적으로 나쁜 습관 일뿐입니다.

class MyClass; 
static MyClass *myClass; 

void doSomething(int (*callback)()) 
{ 
    // Do stuff... 
    int value = callback(); 
    cout << value << "\n"; 
} 

class MyClass 
{ 
public: 
    void things() 
    { 
     value_ = 42; 
     myClass = this; 
     doSomething(myCallback); 
    } 

private: 
    int value_; 

    static int myCallback() 
    { 
     return myClass->value_; 
    } 
}; 

int main() 
{ 
    MyClass object; 
    object.things(); 
    return 0; 
} 
0

재진입 및 비 스레드 안전 방법은 전역 변수를 사용하여 "this"주소를 전달하는 것입니다.

0

static 함수에서 result = SomeComputation();을 이동하고 static 함수를 호출하기 바로 전에 BigFunction에 넣을 수 있습니다.

+0

물론, 그렇지만 나는 기대했던 결과를 얻지 못할 것입니다 ... –

+0

나는 아직도 그렇게 생각합니다. 왜냐하면 참조로 정적 함수에 결과를 보내기 때문입니다. – ahj

+0

저는 실제로 결과 인수를 입력으로 사용할 수 있다고 생각합니다. 그런 식으로 생각하지 않았습니다. 그러나 이것이 단순한 예임을 기억하십시오. 실제로 SomeComputation 함수에 포함 된 것들 중 하나는 객체의 많은 값을 업데이트하기 때문에 실제로 작동하지 않을 수 있습니다. –

관련 문제