python与c++中“类方法“继承再拓展的区别
python与c++中"类方法"继承再拓展的区别
- 用法
- 有何区别?
- py如何自动解决?
- c++
- 总结
用法
(用的时候,只需要知道用法就可以了,后面的不用看了)
- py:
class TestHandlersMixin :def setPlotParams(self,int maxAngle, float t1) # 基础逻辑:初始化图表范围plot.setXRange(0, maxAngle);plot.setT1(t1);class MainWindow(TestHandlersMixin ) :def setPlotParams(int maxAngle, float t1) :super();savedXRange = plot.currentXRange(); # 追加本窗口想要加的逻辑
- C++:
struct TestHandlersMixin {virtual void setPlotParams(int maxAngle, float t1) {// 基础逻辑:初始化图表范围plot.setXRange(0, maxAngle);plot.setT1(t1);}
};struct MainWindow : public TestHandlersMixin {void setPlotParams(int maxAngle, float t1) override {TestHandlersMixin ::setPlotParams(maxAngle, t1); // 相当于 super()savedXRange = plot.currentXRange(); // 追加本窗口想要加的逻辑}
};
用法很简单,仅此而已: py用super ; c++不需要 super,因为必须写 A::f()
有何区别?
区别就在于"钻石问题",python可以自动解决,c++则是需要明确到底调用了谁?
A/ \B C\ /D
py如何自动解决?
py语言制定者,使用C3 线性化规则,就是一条线,顺着就下来了
class A: def __init__(self): print("A"); super().__init__()class B(A): def __init__(self): print("B"); super().__init__()class C(A): def __init__(self): print("C"); super().__init__()class D(B, C): def __init__(self): print("D"); super().__init__()if __name__ == "__main__":D()
# 输出:
# D
# B
# C
# A
| 调用点 | 当前实例类型 | 当前类 | MRO 位置 | super() 调用的下一个类 |
|---|---|---|---|---|
D().__init__ | D | D | 0 | B |
B().__init__ | D | B | 1 | C |
C().__init__ | D | C | 2 | A |
A().__init__ | D | A | 3 | object |
所以:
打印是谁调用了 A.init()?A由 C 的 super().init() 调用
不是 B 调用 A,也不是 D 直接调用 A
而是 C 调用 A,因为在 MRO 中,C 排在 A 前面!
那我如果想要让B调用A,则只需要将
class D(B, C):#D->B->C->Adef **init**(self): print("D"); super().**init**()改为
class D(C, B):#D->C->B->Adef **init**(self): print("D"); super().**init**()所以,“不管是 C 调用 A 还是 B 调用 A,调用的都是同一个 A”
- 再举一个例子
class A:def __init__(self):print(f"A initialized, self.x = {getattr(self, 'x', '未设置')}")super().__init__()class B(A):def __init__(self):self.x = "来自 B"print("B 设置了 x")super().__init__()class C(A):def __init__(self):print("C 没有设置 x")super().__init__()# 情况1:D(B, C)
class D1(B, C):def __init__(self): print("D1"); super().__init__()# 情况2:D(C, B)
class D2(C, B):def __init__(self): print("D2"); super().__init__()print("--- D1 ---")
D1()
print("--- D2 ---")
D2()
- 输出:
--- D1 ---
D1
B 设置了 x
C 没有设置 x
A initialized, self.x = 来自 B
--- D2 ---
D2
C 没有设置 x
B 设置了 x
A initialized, self.x = 来自 B
- 分析
对于D1: D1 -> B(设置A中x值) -> C -> A
对于D2: D1 -> C -> B(设置A中x值) -> A
c++
- 例子1
#include <iostream>
using namespace std;struct A {A() { cout << "A\n"; }
};struct B : A {B() { cout << "B\n"; }
};struct C : A {C() { cout << "C\n"; }
};struct D : B, C {D() { cout << "D\n"; }
};int main() {D d;
}
输出:
A
B
A
C
D
- 例子2
#include <iostream>
using namespace std;struct A {A() { cout << "A\n"; }
};struct B : virtual A { // 关键:virtualB() { cout << "B\n"; }
};struct C : virtual A { // 关键:virtualC() { cout << "C\n"; }
};struct D : B, C { // D 继承 B 和 CD() { cout << "D\n"; }
};int main() {D d;
}
输出:
A
B
C
D
- 例子3
#include <iostream>
using namespace std;struct A {void f() { cout << "A.f\n"; }
};struct B : A {void f() { cout << "B.f\n"; /* 想调用 A.f */ }
};struct C : A {void f() { cout << "C.f\n"; /* 想调用 A.f */ }
};struct D : B, C {void f() { cout << "D.f\n"; B::f(); // 调用 B 的 fC::f(); // 调用 C 的 f}
};int main() {D d;d.f();
}
输出:
D.f
B.f
C.f
总结
那py这种机制还真是完美,c++需要向py学习! 对于面向结果的编程,其实我们不需要知道到底是谁调用了,反正算出来的结果一样不就行了!
