#include <iostream>

using namespace std;

class base
{
protected:
    int x; /*position*/
public:
    base();
    int getX() const; /*get position*/
    void setX(int); /*set position*/
    friend ostream &operator<<(ostream &, base);
};

class A: public base
{
    /*memebers and memeber functions*/
};

class B: public base
{
private:
    int (A::*fp_getA_X)() const = &A::getX; /*pointer to memeber function */
    A const * target = nullptr;
public:
    B(const A*);
    void setA(const A*);
    int getA_X() const;
    friend ostream &operator<<(ostream &, B);
};

B::B(const A* a): target(a){};

void B::setA(const A* a){ target = a; }

int B::getA_X() const 
{
    return target->getX();
    /* return (target->*fp_getA_X)(); // alternative */
}
ostream &operator<<(ostream &os, B b)
{
    os << "a's position (" << b.getA_X() << ")";
    return os;
}

base::base():x(0){}
int base::getX() const { return x; }
void base::setX(int n) { x = n; }
ostream &operator<<(ostream &os, base obj)
{
    os << "(" << obj.getX() << ")";
    return os;
}

int main()
{
    // #: 可以代表任一數字
    /*
    b#們全部一開始得到a1的參考，
    a1.x改變b#們都可以知道，
    而b#也有自己的x (用static_cast<base>(b1)或b1.getX()查看)。
    最後b3變成參考a2，
    a2.x改變b3就可以知道。
    */
    A a1, a2;
    B b1(&a1),b2(&a1),b3(&a1);
    cout << "a1 = " << a1 << endl;
    cout << "b1 : " << b1 << endl;
    cout << "b1 = " << "(" << b1.getX() << ")" << endl;
    cout << "b1 = " << (static_cast<base>(b1)) << endl;
    cout << endl;
    
    a1.setX(2);
    b1.setX(4);
    b2.setX(5);
    b3.setX(6);
    cout << "a1 = " << a1 << endl;
    cout << "b1 : " << b1 << endl;
    cout << "b1 = " << (static_cast<base>(b1)) << endl;
    cout << "b2 = " << (static_cast<base>(b2)) << endl;
    cout << "b3 = " << (static_cast<base>(b3)) << endl;
    cout << endl;
    
    a2.setX(22);
    b3.setA(&a2);
    cout << "a1 = " << a1 << endl;
    cout << "a2 = " << a2 << endl;
    cout << "b1 : " << b1 << endl;
    cout << "b1 = " << (static_cast<base>(b1)) << endl;
    cout << "b2 = " << (static_cast<base>(b2)) << endl;
    cout << "b3 = " << (static_cast<base>(b3)) << endl;
    cout << "b3 : " << b3 << endl;
    cout << endl;
    
    a2.setX(34);
    b3.setX(-2);
    cout << "a2 = " << a2 << endl;
    cout << "b3 : " << b3 << endl;
    cout << "b3 = " << (static_cast<base>(b3)) << endl;

    return 0;
}