2012-06-21

C++ Class Member Function Pointer

#include <string>
#include <iostream>
using namespace std;

class A {
public:
void foo(string s)
{
cout << "A::foo() " << s << endl;
}

void foo2()
{
cout << "A::foo2()" << endl;
}
};

class B {
public:
virtual void foo(string s) = 0;
};

class B1 : public B {
public:
virtual void foo(string s)
{
cout << "B1::foo() " << s << endl;
}
};

class B2 : public B1 {
public:
virtual void foo(string s)
{
cout << "B2::foo() " << s << endl;
}
};


typedef void (*callback1)(string); // normal function pointer
typedef void (A::*callback2)(string); // class A member function pointer
typedef void (B::*callback3)(string); // class B member function pointer
typedef void (A::*callback4)(); // class A member function pointer

int main()
{
// normal function pointer and member function pointer size are different
cout << "size of callback1: " << sizeof(callback1) << endl;
cout << "size of &B::foo  : " << sizeof(&B::foo) << endl;
cout << "size of &B1::foo : " << sizeof(&B1::foo) << endl;
cout << "size of &B2::foo : " << sizeof(&B2::foo) << endl;

A* a1 = new A;
A  a2;
callback2 f1 = &A::foo;

// need an object to call member function
(a1->*f1)("from pointer");
(a2.*f1)("from reference");

B1 b1;
B2 b2;

// use base class' member callback call sub-class
callback3 f2 = (callback3)&B1::foo;
(b1.*f2)("b1");

// use base class' member callback call sub-class
f2 = (callback3)&B2::foo;
(b2.*f2)("b2");

// even can call other class's member function with same signature
f2 = (callback3)&A::foo;
(b1.*f2)("b1");
(b2.*f2)("b2");
// (a2.*f2)("a2"); // can't compile. the object has to be the same type of the callback class

// even can call other class's member function with different signature
f2 = (callback3)&A::foo2;
(b1.*f2)("b1");

// another example to call other class's member function with different signature
callback4 f4 = (callback4)&A::foo;
(a2.*f4)();

// can't assign member function pointer to normal function pointer
// callback1 f3 = (callback1)&A::foo; // can't compile


return 0;
}

/*
 * Compile with g++ on Linux.
 *
 * Output of the program:

size of callback1: 4
size of &B::foo  : 8
size of &B1::foo : 8
size of &B2::foo : 8
A::foo() from pointer
A::foo() from reference
B1::foo() b1
B2::foo() b2
A::foo() b1
A::foo() b2
A::foo2()
A::foo()


 */

面向对象设计原则

摘自《设计模式精解》, 21.2 “面向对象原则的总结”


  • “对象”是负有定义良好的责任的东西
  • 对象对自己负责
  • “封装”意味着任何形式的隐藏:
    • 数据隐藏
    • 类隐藏(藏在抽象类或接口后面)
    • 实现隐藏
  • 使用共同点/变化点分析抽象出行为和数据中的变化点
  • 针对接口进行设计
  • 把继承考虑为一种封装变化的办法,而不是为现有对象制造特殊情况
  • 将变化点封装在一个类中,并使之与这个类中其他的变化点相分离
  • 力求松耦合
  • 力求高内聚
  • 绝对细心地应用“一次并且只有一次”规则