2008年6月11日星期三

C++ friend class

有些時候我們會利用 C++ 中的 friend 關鍵字來設定類別的好友.
但可惜一個 friend 宣告只會對一個類別產生作用:

class Texture {
public:
friend class IResourceLoader;
uint width() const { return mWidth; }
uint height() const { return mHeight; }
private:
uint mWidth;
uint mHeight;
};

class IResourceLoader {};

class JpegLoader : public IResourceLoader {
void load() {
// ...
mTexture.mWidth = 128; // Compiler error!!
}
};

以上的 Texture 類別有成員 mWidth 和 mHeight, 它們都只應由 IResourceLoader 的實作類別所能更改. 幸好有 Inner class 可以幫到我們:

// Texture.h
class Texture {
public:
friend class IResourceLoader;
uint width() const { return mWidth; }
uint height() const { return mHeight; }

// We declare a templated inner class here (but not defined yet)
template class PrivateAccessor;

private:
uint mWidth;
uint mHeight;
};

class IResourceLoader {};

// JpegLoader.cpp
// Define Texture::PrivateAccessor here, access what ever you want
template<>
class Texture::PrivateAccessor {
public:
static size_t& width(Texture& texture) {
return texture.mWidth;
}
static size_t& height(Texture& texture) {
return texture.mHeight;
}
};
typedef Texture::PrivateAccessor Accessor;

void JpegLoader::load() {
// ...
Accessor::width(mTexture) = 128; // Ok! no problem
Accessor::height(mTexture) = 128;
}

你可能會認為這樣做等同把所有成員變為公開 (public), 事實上這個方案的精神在於迫使程序員清楚自己正在做什麼, 而不是錯誤地更改了變數.

沒有留言:

發佈留言