以前寫 Java 時滿習慣用 helper class 分擔主 class 的一些工作, 簡化主 class 本體的複雜度, 或是提供輔助用的 data object, 但只在內部使用, 不讓外部使用。在 Java 裡滿直覺的, helper class 宣告成 package-private 即可。但在 C++ 的情況, 明白 compiler 怎麼編譯 C++ 程式後, 才想通作法。
程式如下:
a.h
class X; class A { public: A(); void print(); private: X* x; }; class B { public: B(); void print(); private: X* x; };
a.cpp
#include <iostream> #include "a.h" class X { public: void print(const char *s) { std::cout << s << std::endl; } }; A::A() : x(new X()) {} B::B() : x(new X()) {} void A::print() { x->print("A"); } void B::print() { x->print("B"); } int main(void) { A a; B b; a.print(); b.print(); return 0; }
兩個關鍵:
- a.h 需要知道 X 是 class, 不是天外飛來的不知名符號, 必須有 forward declaration class X。include a.h 的程式沒有 X 的完整宣告, 自然也無法使用 X
- class A 和 B 不能宣告 member field 為 X x, 必須用指標, 因為在宣告 A 或 B 的物件時, compiler 要知道該在 stack 上配置多少空間, 但 a.h 裡沒提到, 所以除了 a.cpp 以外引入 a.h 的程式也不會知道, 這和 Pimpl 宣告實作物件為指標是同樣的原因。用指標的話則無此問題, 指標不論型別大小都一樣
相較於其它語言, C++ 給我的感覺是, 從思考 Compiler 如何生成程式的角度來看, 會比較容易理解它的語法和限制
沒有留言:
張貼留言