关于隐藏实现代码
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
这个里面,包含了另外的一个测试:即库更新后,
我是否可以不重新编译用户代码。
结论是,可以不用重新编译用户代码。