创建子类的多个实例,其中只有一个超类实例
Creating multiple instances of a subclass, with only one instance of a superclass
我正在尝试实现 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
对象。 - 如果你仍然需要能够互换使用
Block
和Block_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
拥有,并且仅通过引用/指针传递。
- 有一个打印语句的函数是一种糟糕的编程实践吗
- VSCode-有一个红色下划线,但程序构建和运行正确,并且出现配音错误
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 有没有可能有一个只有ADL才能找到的非好友功能
- 我有一个对象,它将在整个程序的持续时间内实例化,但一个类成员不会,我应该动态分配它吗?
- 我有一个类,它创建了另一个类的实例.如何将变量通过第一个类传递到第二个类的实例化中?
- Qt:在一个类中有一个QPainter对象的实例
- 如果我在一个类中有一个静态属性,并创建该类的许多新实例
- C#:Cdecl-DllExport,参数中有一个指向类实例的指针
- 为什么我的程序有一个实例,其中"Vector Subscript out of Range"?
- 同一个c++类的所有实例共享一个vtable,或者每个实例都有自己的vtable
- 我可以有一个要实例化的模板列表,而无需事先实例化
- 我可以有一个异常的静态全局实例吗?
- 使用OOP,当您有一个类的实例作为另一类的属性时,如何可能只在第二个类中实例化它
- javascript中的闭包与c++中的类实例(它有一个私有成员和一个公共方法)相当吗
- 是否可以有一个类,而不创建它的实例
- 在Qt主窗口中,为什么一个实例有一个指向实例的指针
- 如何确保至少有一个类的实例
- 有一个带有c++类的DLL,它的构造函数接受其他c++类,如何使c#能够创建它的实例
- 在MFC,我怎么能有一个按钮来创建几个对话框实例连续不关闭它们