[Python][C++] static method and inheritance

#include <iostream>

using namespace std;

class Parent {
public:
    void foo() {
        cout << "foo of parent" << endl;
    }
    static void static_foo() {
        cout << "static_foo of parent" << endl;
    }
};

class Child : public Parent {
public:
    void foo() {
        cout << "foo of child" << endl;
    }
    static void static_foo() {
        cout << "static_foo of child" << endl;
    }
};

class DummyChild : public Parent {};

void demo() {
    Parent parent;
    Child child;
    DummyChild dummyChild;

    parent.foo();               //foo of parent
    Parent::static_foo();       //static_foo of parent

    child.foo();                //foo of child
    Child::static_foo();        //static_foo of child

    dummyChild.foo();           //foo of parent
    DummyChild::static_foo();   //static_foo of parent

    Parent *parentPtr;
    Child *childPtr;

    parentPtr = &child;
    parentPtr->foo();           //foo of parent
    //在一般的情況下 因為cpp是靜態語言 預設只會去找這個pointer class所屬的member function

    childPtr = &child;
    childPtr->foo();            //foo of child
}
class VirtualParent {
public:
    //member function前面加個virtual就變成virtual function
    //後面再加上 = 0;就是pure virtual function
    virtual void foo() = 0;
    virtual void foo2() {} //實作virtual function不是良好設計 但仍可編譯
};

class NonVirtualChild : public VirtualParent {
public:
    //child必須實作pure virtual function
    void foo() {
        cout << "non virtual child" << endl;
    }
    //若parental有實作virtual function, child建議要overwrite
    //但非強制overwrite
    void foo2() {}
};

void demo1() {
    //含有pure vitual function的class無法生成instance
    //此class又稱abstract class(c++術語)或是interface(抽象講法)
    //VirtualParent p;

    NonVirtualChild c;
    c.foo(); //non virtual child
}

class ConcreteParent {
public:
    virtual void foo() {
        cout << "concrete parent" << endl;
    }
};

class ConcreteChild : public ConcreteParent {
public:
    virtual void foo() {
        cout << "concrete child" << endl;
    }
};

void demo2() {
    ConcreteParent* p = new ConcreteChild();
    p->foo(); //concreate child;
    //若呼叫的是virtual function, pointer會去table找出真正的member function
    delete p;
}

int main() {
    demo();
    demo1();
    demo2();
}

#Python
class Parent:
	variable_foo = "variable_foo" #也是class variable
	class_variable_foo = "class_variable_foo"

	def __init__(self):
		self.variable_foo = "init_foo" #object variable

	def foo(self):
		print("foo of parent, variable = {}, {}".format(self.variable_foo, self.class_variable_foo))

	@staticmethod
	def static_foo(*arg):
		print("static_foo of parent: arg = {}".format(arg))

	@classmethod
	def class_foo(cls):
		print("class_foo of parent, variable = {}, {}".format(cls.variable_foo, cls.class_variable_foo))

class Child(Parent):
	variable_foo = "child_variable_foo" #也是class variable

	def __init__(self):
		self.variable_foo = "init_child_foo" #object variable

	def foo(self):
		print("foo of child, variable = {}, {}".format(self.variable_foo, self.class_variable_foo))

	@staticmethod
	def static_foo(*arg):
		print("static_foo of child: arg = {}".format(arg))

	@classmethod
	def class_foo(cls):
		print("class_foo of child, variable = {}, {}".format(cls.variable_foo, cls.class_variable_foo))

	class DummyChild(Parent):
		pass

parent = Parent()
parent.foo() # foo of parent, variable = init_foo, class_variable_foo
#Python會先去找object的variable 找不到時才會去找class的variable

Parent.class_foo() # class_foo of parent, variable = variable_foo, class_variable_foo
Parent.variable_foo = "changeable"
Parent.class_foo() # class_foo of parent, variable = changeable, class_variable_foo
#在Python裡面 class也是一個object 故在執行期改變class變數是OK的
#在C++ class不是object而是一個namespace 故呼叫class static function要用"::" 而非"."

Parent.static_foo() # static_foo of parent: arg = ()
Parent.static_foo("argument1", "arguments2") # static_foo of parent: arg = ('argument1', 'arguments2')
#在Python裡面 static method是沒辦法access class的attribute
#故可了解 Python的class method其實比較像C++的class static method

child = Child()
child.foo() # foo of child, variable = init_child_foo, class_variable_foo
child.class_foo() # class_foo of child, variable = child_variable_foo, class_variable_foo
child.static_foo() # static_foo of child: arg = ()

dummy = DummyChild()
dummy.foo() # foo of parent, variable = init_foo, class_variable_foo
DummyChild.class_foo() # class_foo of parent, variable = changeable, class_variable_foo
DummyChild.static_foo() # static_foo of parent: arg = ()