전혀 다른 클래스의 함수로 함수 포인터를 매개변수로 전달하는 법?

wltjd666의 이미지

2개의 해더파일과 2개의 소스파일이 있는데요, 최대한 요약하자면 ....

//------------MyClass.h------------
#include <iostream>
 
class MyClass
{
private:
  int n_X;
  int n_Y;
 
public:
  void MyFunc1(int *x, int *y);
  void MyFunc2(int x, int y);
};
//---------------------------------
 
 
//-------------Master.h------------
#include <iostream>
 
class Master
{
private:
  void(*m_Func1)(int *x, int *y);
  void(*m_Func2)(int x, int y);
 
public:
  void SetFunc(
     void(*p_Func1)(int *x, int *y),
     void(*p_Func2)(int x, int y));
};
//---------------------------------
 
 
//-----------Function.cpp----------
#include <iostream>
#include "MyClass.h"
#include "Master.h"
 
void Master::SetFunc(
   void(*p_Func1)(int *x, int *y),
   void(*p_Func2)(int x, int y))
{
  m_Func1 = p_Func1;
  m_Func2 = p_Func2;
}
 
void MyClass::MyFunc1(int *x, int *y)
{
  n_X = x;
  n_Y = y;
}
 
void MyClass::MyFunc2(int x, int y)
{
  n_X = x;
  n_Y = y;
}  
//---------------------------------
 
 
//--------------Main.cpp-----------
#include <iostream>
#include "Master.h"
#include "MyClass.h"
 
int main()
{
  Master *master = new Master();
  MyClass *mclass = new MyClass();
 
  master->SetFunc(
     mclass->MyFunc1,
     mclass->MyFunc2);
 
  delete master;
  delete mclass;
 
  return 0;
}
//---------------------------------

master->SetFunc(...) 이 부분에서 오류가 납니다. &를 사용해서 멤버 포인터를 만들라는데..
무슨 소린가요?

익명 사용자의 이미지

#1
mclass->MyFunc1를 저장할 함수 포인터는 void (MyClass*)::(p_Func1)(int, int) 와 같이 써줘야합니다. void(p_Func1)(int *x, int *y) 가 아니구요. 생각해보세요. 멤버 함수는 this 포인터를 보이지 않는 인자로 가지고 있습니다. 그렇지 않으면 제대로 작동할 리가 없지요. 함수 포인터의 타입에도 이 사실이 반영되어야겠지요. 따라서 멤버 함수가 보통 함수와 타입이 같은 수는 없습니다. (MyClass*) 부분이 이게 어느 클래스의 멤버 함수인지를 알려주는 부분입니다. 즉 this 포인터에 해당하는 암묵적인 인자의 타입을 써주는 겁니다.

#2
그리고 멤버 함수만 저장해서는 아무것도 할 수 없습니다. this 포인터에 해당하는 데이터가 있어야지만 저장한 멤버 함수를 호출할 수 있겠지요. 예를 들어 SetFunc 가 mclass 를 같이 받아서 저장하거나 해야합니다. 뭐 꼭 그게 아니더라도 여하튼 m_Func1 이나 m_Func2 를 호출하기 위해서는 반드시 MyClass 타입의 객체가 필요합니다.

#3

참고. https://isocpp.org/wiki/faq/pointers-to-members

wltjd666의 이미지

그럼 MyClass의 내용을 전부 Master 클래스로 옮겨서 하나의 클래스로 쓰는 방법으로 하면 가능한가요?

익명 사용자의 이미지

질문이 무슨 뜻인지 모르겠군요.

wltjd666의 이미지

MyClass 클래스 자체를 없애고 그냥 Master 클래스로 통합하여,
master->SetFunc(master->MyFunc1,master->MyFunc2);
로 쓰는 겁니다.

익명 사용자의 이미지

무엇 때문에 그렇게 하지요? 앞서 말씀드렸듯이 멤버 함수 포인터를 저장할 타입을 정확하게 써주고 MyClass 타입의 객체를 같이 저장하면 되는 일입니다. 처음에 MyClass와 Master를 다른 클래스로 디자인한 이유가 있을텐데 별다른 이유도 없이 그 둘을 합칠 필요가 없지요.

wltjd666의 이미지

계속 물어봐서 죄송한데요. 잘 이해가 안되서요..
Main.cpp, Function.cpp, MyClass.h, Master.h에서 어떤 함수를 건드려야 하는 건가요?

...!의 이미지

#include <iostream>
 
using namespace std;
 
struct S {
	S(int y)
	: y(y) {
	}
 
	void foo(int x) {
		cout << x + y << endl;
	}
 
	int y;
};
 
int main() {
	S s1(10);
 
	//Compile error. "객체에 바인딩된 멤버 함수의 주소" 라는 것은 존재하지 않음 또는 의미 없음.
	//void(*func_p)(int) = &s1.foo;   
 
	//Compile error. "클래스 S의 멤버 함수 foo의 주소"는 존재함 또는 의미 있음 . 
	//그러나 좌변과 우변의 타입이 달라서 이런 대입(초기화)은 불가능함.
	//void(*func_p)(int) = &S::foo;   
 
	void (S::*func_p)(int) = &S::foo; // OK
 
	(s1.*func_p)(1); // func_p 를 호출하려면 S 타입의 객체가 필요함. 괄호에 주의. 결과는 11.
 
	S s2(20);
	(s2.*func_p)(1); // 결과는 21.
	return 0;
}

잘 살펴보세요. 본인 코드에 응용하실 수 있을겁니다. 그리고 글을 작성할 때에 <code> </code> 대신 <cpp> </cpp> 를 쓰면 C++ 문법에 맞춰 구문 강조를 해주니 더 보기 좋습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.