2012年11月3日 星期六

C++ 隱藏共用的 helper class

以前寫 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 如何生成程式的角度來看, 會比較容易理解它的語法和限制

沒有留言:

張貼留言

在 Fedora 下裝 id-utils

Fedora 似乎因為執行檔撞名,而沒有提供 id-utils 的套件 ,但這是使用 gj 的必要套件,只好自己編。從官網抓好 tarball ,解開來編譯 (./configure && make)就是了。 但編譯後會遇到錯誤: ./stdio.h:10...