- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我打算编写一个代码,其中包含具有如下继承关系并具有与 Material 类型关联的各种属性的类:
Foo
。没有与之关联的属性。Foo1GeneralElastic
继承自 Foo 类并具有与可能各向异性弹性 Material 相关的属性。Foo2GeneralElastic
也继承自类 Foo 并具有与 Foo1GeneralElastic
相同种类的 Material 属性,但在其他方面有所不同。Foo1PiezoElastic
继承自 Foo1GeneralElastic
,具有压电特性和一般弹性特性。Foo1IsotropicElastic
继承自 Foo1GeneralElastic
,但不共享其属性。我决定抽象基类将有一个或多个方法采用 MyPropMap
类型的映射,定义为:
typedef std::map<PropertyLabel,std::vector<double> > MyPropMap
对于 PropertyLabel 类型可能有几种不同的选择,我正在尝试权衡每种选择的优缺点:
让 PropertyLabel 成为一个 enum
:这将是轻量级的,但它基本上是一袋标签,用于我所使用的每种 Material 的所有不同属性考虑。
让 PropertyLabel 只是一个 int
:在这里,我为每种 Material 类型准备了单独的头文件,每个头文件都包含静态整数常量的定义将是相关 Material 属性的标签。例如,MatPropKeyGenElastic.hpp
将定义整数常量 ELASTICITY_MATRIX
,MatPropKeyIsotropicElastic.hpp
将定义常量 ELASTIC_MODULUS
和POISSONS_RATIO
和 MatPropKeyPiezoElastic.hpp
将#include
文件 MatPropKeyGenElastic.hpp
并另外定义常量 PIEZO_CONST_MATRIX
。
棘手的事情是确保没有任何可以一起使用的常量具有相同的值。这可以通过使用将这些常量的值设置为唯一值的脚本生成头文件来实现。
让 PropertyLabel 成为 std::string
从这里我可以采取几种不同的方式。我可以在代码中使用像 "ELASTICITY_MATRIX"
这样的字符串文字,并依赖于这些文字永远不会被拼错——一个会在运行时而不是编译时捕获的错误。我可以用类似于上述整数常量方案的方式定义字符串常量,保持常量唯一性的任务很简单:只需将 ELASTICITY_MATRIX
的值设置为 "ELASTICITY_MATRIX"
,POISSONS_RATIO
到 "POISSONS_RATIO"
的值,等等。
我看到的问题是,除了额外的开销之外,我已经看到了与非 POD 的全局静态常量相关的恐怖故事,例如主题 non-integral constants 中的评论中的故事。和 Defining class string constants in C++? .我想我可以将全局静态常量设置为 const char[]
数组,这些 POD 在用作映射键时会隐式转换为 std::string
(而且,不,我不打算让 map 键本身成为 const char*
)。我还可以使用预处理器定义字符串文字,但我无法将它们保存在命名空间中。
您会推荐上述任何一种方法吗?它们中是否有我没有注意到的隐藏陷阱?您是否还有其他方法可以推荐?
最佳答案
我不推荐使用字符串。对于这样简单的任务来说太昂贵了。我投票给枚举。
但是如果将所有标签常量放在一个地方看起来太难看,您可以详细说明更复杂的方法 - 使用复合键,如两个数字对 -(类 ID,属性 ID)。
两者都可以定义为枚举,也许是嵌套的。此外,类 ID 可以自动生成 - 例如在 std::type_info
指针上使用 reinterpret_cast
或仅使用 std::type_info
指针或 std::type_index
如果支持的。用代码说明想法:
// PropertyLabel type, could be used as associative container key
struct PropertyLabel: std::pair<const std::type_info*, int>
{
// Template ctor allows implicit conversion from enums
// (actually not only from enums but from any int-compatible types)
// Uncomment explicit keyword if implicit conversions scares you and use
// explicit conversion syntax - PropertyLabel(smth).
template <typename T> /*explicit*/ PropertyLabel(T label):
std::pair<const std::type_info*, int>(&typeid(T), label)
{
}
};
// First property holder
class PropertyUser1
{
public:
enum Labels
{
eProperty1,
eProperty2,
eProperty3,
};
};
// Second property holder
class PropertyUser2
{
public:
enum Labels
{
eProperty1,// Due to class scope you could use same names for different properties
eProperty2,
eProperty3,
};
};
// Usage. A bit dangerous due to implicit conversions, but intuitive and handy:
MyPropMap properties;
properties[PropertyUser1::eProperty1].push_back(42.0);
properties[PropertyUser2::eProperty1].push_back(42.42);
// Will be with explicit ctor:
// properties[PropertyLabel(PropertyUser1::eProperty1)].push_back(42.0);
// properties[PropertyLabel(PropertyUser2::eProperty1)].push_back(42.42);
看起来它可以通过更多类型安全性来改进,从而消除使用非枚举类型(如 int
)的可能性,例如禁用像 PropertyLabel(42)
这样的调用。但这只是为了说明想法。
关于c++ - 用于设置相关类属性的 map 的合理键类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12253613/
我有一个曾经是 TreeView 控件的菜单,但现在我想让每个项目更加直观,并向树中的每个对象添加更多信息。 我的第一个意图是制作一个代表项目的用户控件,并在运行时将它们添加到面板中。这是一个好方法吗
我是 Docker 新手,想知道是否有可能(并且是一个好主意)在 Docker 容器中进行开发。我的意思是创建一个容器,执行 bash,安装和配置我需要的一切,然后开始在容器内进行开发。 容器将成为我
在 Java 中: Parent obj = new Child(); 我创建了一个 Parent 类型的对象。我假设我只能调用父类中定义的方法。因此,我无法调用 Child 中定义的“附加”方法或访
注意:我省略了其他两个阶段(V 和 W)的代码,示例中不需要。 我很确定,我这样处理“开”和“关”时间的方式并不是一种有效的方式。 我想使用查找表实现“开”和“关”脉动。计时器应与表的当前选定值进行比
当代码中包含 Java instanceof 运算符时,许多人会扬起眉毛并说这是禁忌。例如,在这个 other SO Q&A ,答案说: Note that if you have to use th
我是一名优秀的程序员,十分优秀!