c++ - 使用静态分配的派生类对象初始化基类指针数组
问题描述
我有一些类旨在保存指向某些变量的指针,以及与变量相关的一些其他属性。实际上,我正在尝试为 STM32 设计一个 CANopen 堆栈,并且我打算使用这些类来表示对象字典。
以下是这些类的简化版本:
class Object {
public:
constexpr Object(int index) : index{index} {}
private:
int index;
};
class Single : public Object {
public:
constexpr Single(int index, void* var, std::size_t size)
: Object{index}, ptr{var}, size{size} {}
private:
void* ptr;
std::size_t size;
};
class Array : public Object {
public:
constexpr Array(int index, void* var, std::size_t size, std::size_t length)
: Object{index}, ptr{var}, size{size}, length{length} {}
private:
void* ptr;
std::size_t size;
std::size_t length;
};
我希望创建一个这些对象的数组。下面的代码编译没有问题:
int a {1}; // Single variable
float b[] {2.0, 3.0}; // Array
const Object* dictionary[] {
new Single(0x1000, &a, sizeof(int)),
new Array(0x1001, b, sizeof(float), std::size(b))
};
问题是,我尽量避免使用堆(动态分配)。嵌入式系统中动态分配的使用是一个有争议的主题,但我主要关心的是内存利用率:STM32 微控制器的闪存 ROM 比 RAM 多得多,因此最好将变量标记为const
,因此链接器可以将它们放入 ROM 中内存。
但是当修改如下代码时,它不会编译:
const Object* dictionary[] {
&Single(0x1000, &a, sizeof(int)),
&Array(0x1001, b, sizeof(float), std::size(b))
};
它给出了error: taking address of rvalue
错误。
我可以想到一种解决方案:
const Single a_obj {0x1000, &a, sizeof(int)};
const Array b_obj {0x1001, b, sizeof(float), std::size(b)};
const Object* dictionary[] {
&a_obj,
&b_obj
};
这可以毫无问题地工作,并将a_obj
&b_obj
放入 ROM。但我觉得它看起来很丑。它迫使我定义和维护额外的变量集,并想象如果你有大约 20 个变量会怎样。有没有更清洁的方法?
解决方案
我有点疯了,所以...
template<int index, auto& var>
constexpr Single Single_v{index, std::addressof(var), sizeof(var));
template<class T, std::size_t N>
constexpr Array MakeArray( int index, T(&arr)[N] ) {
return {index, arr, sizeof(T), N};
}
template<std::size_t index, auto& Arr>
constexpr Array Array_v = MakeArray( index, Arr );
const Object* dictionary[] {
&Single_v<0x1000, a>,
&Array_v<0x1001, b>,
};
这可能会奏效。
请注意,具有相同参数的两个对象最终成为同一个对象。
这些模板变量可以获取它们的地址,并且是constexpr
.
我们甚至可以走得更远
template<class T, std::size_t N>
constexpr Array MakeObject(int index, T(&arr)[N]) {
return {index, arr, sizeof(T), N};
}
template<class T>
constexpr Single MakeObject(int index, T& obj) {
return {index, &obj, sizeof(T)};
}
template<int index, auto& x>
constexpr auto Object_v = MakeObject(index, x);
现在你可以
const Object* dictionary[] {
&Object_v<0x1000, a>,
&Object_v<0x1001, b>,
};
我们得到了编译时多态正确的对象类型。
您可以使用模板参数参数执行的操作有一些限制,但我没有看到这里有任何影响。
推荐阅读
- stylus - 从手写笔变量评估规则
- c# - EF 核心使用通用工厂注册数据库上下文
- c# - 嵌套类
- : 如何访问列表中的嵌套类?
- python - 如何在 Pandas 列中将科学记数法转换为所需的小数
- ruby-on-rails - ActiveRecord::StatementInvalid: PG::UndefinedTable 在多对多关系中但表存在
- c - 在 Nucleo-F401RE 上使用 DMA 配置 ADC 会产生不稳定的值
- css - 在 2 个单独的表格中选择“selected”类的第一个和最后一个“td”元素
- javascript - react组件构造后如何让函数运行?
- php - 将表情符号从 php Web 应用程序传递到 Oracle db 和 mysql
- python - 当小数> = 1时,pandas / numpy round() 如何工作?