创建子类的多个实例,其中只有一个超类实例

Creating multiple instances of a subclass, with only one instance of a superclass

本文关键字:实例 有一个 超类 创建 子类      更新时间:2023-10-16

我正在尝试实现 Flyweight 模式,但我不太确定继承是如何工作的,所以我不太确定这种模式是如何工作的。

假设我有一个超类,它包含所有"重"信息——纹理等,内在信息(永不改变的信息(。

class Block{
public: //for the sake of the example
Texture tex; 
etc.
};

我有一个 light 类,其中包含更改的数据:

class Block_light : public Block {
public:
int posX, posY, posZ;
int color;
etc.
};

那么,如果我在 main 创建 n 个Block_light,我是否也会创建 n 个Block或者它们都会绑定到一个实例?

int main(){
std::vector<Block_light> blocks(n);
return 0;
};

我是否创建了 n 个Block_light和 1 个Block或 n 个Block_light和 n 个Block?如果是后者,我怎样才能让它只使用一个实例?

C++对象模型确保子类(即派生类(的每个实例也包含其所有超类(即类(的自己的实例。

在您的情况下,这意味着每个Block_light对象都将具有所有Block_light属性,以及具有所有Block属性的Block子对象。换句话说,Block_light一点也不轻。

如果要共享单个公共状态:

  • 您可以使用组合而不是继承:Block_light不会从Block继承,而是引用共享Block对象。
  • 如果你仍然需要能够互换使用BlockBlock_light,你可以使两者从公共接口(即只有虚函数而没有状态的clss(继承IBlock
  • 您也可以使用蝇量级模式,其中状态的某些部分(共享或非共享(被"外部化"为外部状态。这种模式的特殊性在于,对外部状态的引用由调用者提供给类函数,因此 flyweight 对象不需要存储指向此类状态的指针。

第一个选项如下所示:

class Block {...}; 
class Block_light {       // no inheritance 
shared_ptr<Block> b;  // but (private) composition   
...
};  

第二个选项是:

class IBlock {  // no member variables
public:
virtual Texture get_texture()=0;
virtual ~IBlock(){}; 
};  
class Block : public IBlock {  // sharable state
Texture tex; 
public: 
Texture get_texture() override { return tex; }
};    
class Block_light : public IBlock {
shared_ptr<IBlock> b;  // or IBlock or Block depending on the needs.  
public:
Block_light (shared_ptr<IBlock>i) : b(i) {}
Texture get_texture() override { return b->get_texture(); }
};  
int main() { // just a perfectible quick example
auto myb=make_shared<Block>();
Block_light b1(myb);
b1.get_texture();
}

最后一个将像这样使用:

int main() { // just a perfectible quick example
Block myb;     // shared part; 
Block_light bl;
bl.get_texture(myb);
}

我不会详细介绍蝇量级实现,但这里有一个例子。 但是,在选择此模式之前请三思而后行,因为提供共享上下文可能具有挑战性且容易出错。

你实现的不是轻量级模式。没有Block_light这样的东西,而是Block是一个纯粹的接口,由类似Block1的东西提供的实现,看起来像你的Block定义的样子。

例如:

#include <string>
#include <unordered_map>
#include <memory>
class BlockState {
public:
int posX, posY, posZ;
int color;
};
struct Texture {
Texture(const std::string &);
char data[8196];
};
class Block {
public:
Block(std::string) {};
virtual void render(const BlockState &state) const = 0;
};
class Block1 final : public Block {
public:
Block1(std::string name) : Block(name), tex(name) {};
void render(const BlockState &state) const override;
private:
const Texture tex;
};
class BlockFactory final {
public:
std::shared_ptr<const Block> getBlock(const std::string &key) {
auto it = dict.find(key);
if(it != dict.end()) return it->second;
auto it2 = dict.try_emplace(key, std::make_shared<Block1>(key));
return it2.first->second;
}
private:
std::unordered_map<std::string, std::shared_ptr<const Block>> dict;
};
void render () {
static BlockFactory factory;
BlockState a, b;
factory.getBlock("brick")->render(a);
factory.getBlock("brick")->render(b);
}

BlockFactory正在为您管理Block的实例,由不可见的Block1实现实现。使用不同的工厂进行测试等,您可以根据需要切换下面的实现以进行测试。

您的"每个实例"状态不是从Block继承的,而是按值保持独立,其中Block实例由BlockFactory拥有,并且仅通过引用/指针传递。

相关文章: