// 我们这些自虐者们,在使用C++时,会遇到各种各样让人很头疼的问题,其中一个就是类声明。因为我们知道,类有公开成员和私有成员两大类,按照道路来说,无论如何在头文件中都不需要列出隐藏成员。 // 比如这个类: class fuck { public: int Value(); private: int m_value; }; // 我们并不希望在类声明中列出私有成员,因为这会有很大的问题,上面这个类看上去没什么问题,但如果是这样呢? #include <SDL2/SDL.h> #include <windows.h> class fuck { public: ... private: SDL_Surface* m_surface; HANDLE m_xxx; ... }; // 你会看到,声明这个类,还需要包含两个重量级头文件,任何引用这个头文件的模块,都会被污染名称空间,不但会有函数、类型重名的隐患,还带来增加编译时间等各种各样非常FUCK的问题。 // 然而C++是一个异类,因为其为了“兼容C”的蛋疼决策,没有提供模块机制,所以每个.cpp都需要看到所有的东西,只要你想new一个类,都必须要要知道这个类的一切,才能正常的fuck一个class,因为C++需要知道,alloc一个类需要多少内存。// 所以,如果想不用在类声明中列出私有成员,就需要使用各种蛋疼手法。我在这里介绍的就是一种主流的手法:FCCM。
为什么需要这样,还有一个很重要的原因,就是如果在类声明中列出私有成员,就会带来高耦合的蛋疼问题,你改变类的私有成员,每一个使用这个类的.cpp都需要重新编译,严重时可能还需要修改代码。
为了解决这个问题,一些自虐者们研究出了一种称为FCCM的手法,如下所示:
// fuck.h class fuck { public: ... private: class FuckCPP; FuckCPP* m; }; // fuck.cpp #include <SDL2/SDL.h> #include <windows.h> #include "fuck.h" class fuck::FuckCPP { public: SDL_Surface* surface; HANDLE xxx; ... }; fuck::fuck():m(new FuckCPP){m->surface = ...} fuck::~fuck(){} ... // cao.cpp #include "fuck.h" void begin_fuck() { fuck a; a.Fuck("c++"); ... }
总是要class FuckCPP; FuckCPP* m;就显得蛋疼了,所以我们可以将这段咒语弄成一个宏。
// fccm.h #include <memory> #define FUCK_CPP_CLASS_MODEL private: class FuckCPP; unique_ptr<FuckCPP> m; // fuck.h #include "fccm.h" class fuck { FUCK_CPP_CLASS_MODEL public: void Fuck(const string& target); ... }; // fuck.cpp #include <SDL2/SDL.h> #include <windows.h> #include "fuck.h" class fuck::FuckCPP { public: SDL_Surface* surface; HANDLE xxx; ... }; fuck::fuck():m(new FuckCPP){} fuck::~fuck(){} ... // cao.cpp #include "fuck.h" void begin_fuck() { fuck a; a.Fuck("c++"); ... }
这样,每个有类声明的头文件中包含fccm.h就行了,或者直接将那个宏放到类似stdafx.h这样的文件中。FUCK_CPP_CLASS_MODEL也是fccm手法的名称的来历,四个单词的首字母缩写。
细心的自虐者们可能还发现了,这样虽然非常有效的隐藏了私有成员,但在类定义中还是有些小问题,比如每个构造函数都重复了这段咒语:m(new FuckCPP),那么是不是也能弄个宏呢?
#define BEGIN_FUCK_CPP_CLASS_MODEL :m(new FuckCPP) // fuck.cpp ... fuck::fuck() BEGIN_FUCK_CPP_CLASS_MODEL {} ...
然而这并没有可行性,因为会带来一些莫名其妙的问题,比如在构造函数中会参数时,那么就需要很多个宏来满足1、2、3、···、n个参数的情况,所以不适用。
这就是C++让蛋疼的地方,你总是能遇到问题,你总是能解决问题,你总是解决的不完善。
好了,这期技术分享到此介绍,谢谢大家观看,FCCM。