#include <iostream>
using namespace std;
void MyFunc() {
cout << "MyFunc" << endl;
}
int MyFuncA(int intval) {
return intval;
}
int MyFuncB(int intval) {
return intval;
}
int main() {
// const を付与したい場合
void (*const FP)() = MyFunc;
FP(); //=> MyFunc
// 同じ型の関数ポインタは配列で利用可能
int (*const FP_AB[])(int intval) = {
MyFuncA, MyFuncB
};
cout << FP_AB[0](1) << endl; //=> 1
cout << FP_AB[1](1) << endl; //=> 1
// 関数ポインタの型は長ったらしいので typedef することが多い
typedef int (*FpMyFuncAB)(int intval);
const FpMyFuncAB FP_A = MyFuncA;
cout << FP_A(1) << endl; //=> 1
return 0;
}
#include <iostream>
using namespace std;
class MyClass {
public:
static void Show();
private:
typedef void (*FpShow)();
public:
static const FpShow FP_SHOW;
private:
static const int m_intval; // static const は通常クラス内で初期化するが
// https://www.qoosky.io/techs/fc41205299
};
void MyClass::Show() {
cout << m_intval << endl;
}
const MyClass::FpShow MyClass::FP_SHOW = MyClass::Show;
const int MyClass::m_intval = 1; // static const であってもここで初期化できる
int main() {
MyClass::Show(); //=> 1
MyClass::FP_SHOW(); //=> 1
return 0;
}
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass(int intval);
public:
void Show();
void SShow();
private:
typedef void (MyClass::*FpShow)(); // 静的メンバ関数と異なり "MyClass::" が必要
public:
static const FpShow FP_SHOW; // オブジェクトが異なってもメンバ関数のアドレス自体は一定。
// (メモリ上のある定位置に展開されているメンバ関数に渡す、オブジェクトのアドレスが毎回異なるだけ)
// そのため、オブジェクト間で FP_SHOW を共有しても問題にならない。
private:
int m_intval;
};
const MyClass::FpShow MyClass::FP_SHOW = &MyClass::Show; // 静的メンバ関数ポインタと異なり & が必要
MyClass::MyClass(int intval) :
m_intval(intval)
{
}
void MyClass::Show() {
cout << m_intval << endl;
}
void MyClass::SShow() {
// メンバ関数ポインタ FP_SHOW に呼び出しもとオブジェクト this を渡します。
// "->*" や ".*" は渡すための演算子です。演算の優先順位が低いため、全体を () で囲みます。
(this->*FP_SHOW)();
}
int main() {
MyClass objA(1);
MyClass objB(-1);
objA.Show(); //=> 1
objB.Show(); //=> -1
(objA.*MyClass::FP_SHOW)(); //=> 1
(objB.*MyClass::FP_SHOW)(); //=> -1
MyClass* ptrA = &objA;
MyClass* ptrB = &objB;
(ptrA->*MyClass::FP_SHOW)(); //=> 1
(ptrB->*MyClass::FP_SHOW)(); //=> -1
objA.SShow(); //=> 1
objB.SShow(); //=> -1
return 0;
}
アップキャスト時の仮想関数の呼び分けは正常に行われます。
#include <iostream>
using namespace std;
class MyClass {
public:
virtual ~MyClass() {}
public:
virtual void Show();
};
class MySubClass :
public MyClass
{
public:
virtual void Show();
};
void MyClass::Show() {
cout << "MyClass::Show" << endl;
}
void MySubClass::Show() {
cout << "MySubClass::Show" << endl;
}
int main() {
MySubClass obj;
MyClass& ref = obj; // アップキャスト
ref.Show(); //=> MySubClass::Show
void (MyClass::*fp)() = &MyClass::Show;
(ref.*fp)(); //=> MySubClass::Show
// ↑仮想関数の呼び分けが正常に行われた (MyClass::Showとはならない)
return 0;
}