關于隱藏實現代碼
C++ 一直沒有學明白,對于一些問題,一直也沒有解決。
今天嘗試解決的問題,來源于微軟如何把它的庫實現隱藏起來。
之前的想法是,不管定義何種類和方法,總應該在頭文件中出現聲明,
從而,一些private的方法和變量我們也應該可以推斷出來。
但是,事實并不是這樣,很多時候,看到的只是public的。
而從理論上來說,應該將實現與接口分離。像微軟提供的頭文件,
的確已經定義好了固定的接口。而這樣,它們只需要再提供類庫,
我們就可以用了。
定義接口
首先,定義一個稱為 MyClass 的類,為了方便,我創建了一個目錄,
專門用于存放編譯我們自己類庫的代碼。
MyClass.h 的代碼非常簡單:
#ifndef MyClass_H
#define MyClass_H
class MyClass {
public:
void run();
};
#endif
這個之后會暴露給用戶。但我們先不進行實現。
實現隱藏代碼
下面,做的是真正的工作,即我們不需要給用戶看的。
定義 PrivateMyClass.h 和 PrivateMyClass.cpp 。
PrivateMyClass.h 內容很簡單:
#ifndef PrivateMyClass_H
#define PrivateMyClass_H
class PrivateMyClass {
public:
void canrun();
};
#endif
PrivateMyClass.cpp 也簡單:
#include <iostream>
#include "PrivateMyClass.h"
void PrivateMyClass::canrun() {
std::cout << "Begin Can RUN?" << std::endl;
std::cout << "End Can RUN?" << std::endl;
}
封裝隱藏代碼
然后,我們在 MyClass 的實現中,調用 PrivateMyClass 。
MyClass.cpp 內容:
#include <iostream>
#include "MyClass.h"
#include "PrivateMyClass.h"
void MyClass::run() {
std::cout << "Begin RUN" << std::endl;
PrivateMyClass pmc;
pmc.canrun();
std::cout << "End RUN" << std::endl;
}
編譯生成動態庫
有了這些,就可以編譯出動態庫了,寫一個 Makefile :
lib:MyClass.o PrivateMyClass.o
g++ -g -shared -o libresult.so MyClass.o PrivateMyClass.o
MyClass.o:MyClass.cpp MyClass.h
g++ -fPIC -Wall -g -c MyClass.cpp
PrivateMyClass.o:PrivateMyClass.cpp PrivateMyClass.h
g++ -fPIC -Wall -g -c PrivateMyClass.cpp
給出頭文件和動態庫
這樣,我們就可把 MyClass.h 和 libresult.so 給用戶了。
我放到public的目錄下。
測試
為了確保正常運行,寫代碼測試一下:
#include "MyClass.h"
int main() {
MyClass mc;
mc.run();
}
然后是Makefile:
all:exe
LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH ./result
test1:exe
LD_LIBRARY_PATH=../private/:$LD_LIBRARY_PATH ./result
test2:exe
LD_LIBRARY_PATH=../private-v2/:$LD_LIBRARY_PATH ./result
exe:TestClass.o
g++ -o result TestClass.o -L. -lresult
TestClass.o:TestClass.cpp
g++ -c TestClass.cpp
這個里面,包含了另外的一個測試:即庫更新后,
我是否可以不重新編譯用戶代碼。
結論是,可以不用重新編譯用戶代碼。