提问人:T. R. Bernstein 提问时间:9/19/2023 最后编辑:user17732522T. R. Bernstein 更新时间:9/19/2023 访问量:48
使用指向 C++ 中临时静态分配对象的引用/指针初始化多态 C 数组 [已关闭]
Initialize polymorphic C array with references/pointers to temporary statically allocated objects in C++ [closed]
问:
问题
是否可以使用指向 C++ 中临时对象的引用/指针初始化多态 C 数组(例如 ParentClass
* 类型的数组,包含 Subclass1*、Subclass2*
等类型的指针)?
由于在编译时都是已知的,我不想使用或任何具有动态分配的东西,例如使用 .
temporary objects
unique_ptr
new
用例
目前版本
鉴于
class Command {
public:
virtual void run(const vector<string>& args) = 0;
};
class Generate: public Command {
public:
void run(const vector<string>& args) override;
};
class Scan: public Command {
public:
void run(const vector<string>& args) override;
};
我想定义一个包含数据成员的类,例如:App
static Command* commands[]
// App.hpp
class App {
static Command* commands[];
}
// App.cpp
Generate generate;
Scan scan;
Command* App::commands[] {&generate, &scan};
编译器错误
在尝试寻找有效的解决方案时,我遇到了以下编译器错误列表:
taking the address of a temporary object of type 'Generate':
Command* App::commands[] {&Generate()};`
non-const lvalue reference to type 'Generate' cannot bind to a temporary of type 'Generate'
Command* App::commands[] {&static_cast<Generate&>(Generate())};
cannot initialize an array element of type 'Command *' with an rvalue of type 'const Generate *'
Command* App::commands[] {&static_cast<const Generate&>(Generate())};
编译器:。g++: Apple clang version 15.0.0 (clang-1500.0.29.1)
寻求的改变
它希望删除全局变量并改用临时对象,例如:App.cpp
generate
scan
// App.cpp
Command* App::commands[] {&Generate(), &Scan()};
更好的是,直接在 中去掉和定义,例如:App.cpp
commands
App.hpp
// App.hpp
class App {
static Command* commands[] {&Generate(), &Scan};
}
// App.cpp is deleted
答:
是的,但不是指针。它只能使用数组来聚合包含引用成员的类:
struct CommandRef {
Command&& command;
};
/* DO NOT USE, SEE BELOW */
CommandRef App::commands[] {{Generate()}, {Scan()}};
但是,我强烈建议不要这样做,因为上述内容依赖于非常特殊的生存期扩展规则来绑定聚合初始化中的引用。
它很容易被错误地做出未定义的行为,尤其是在缺乏对正式生命周期规则的理解的情况下,例如
- 创建非聚合类。
CommandRef
- 在聚合初始化中使用 / 而不是 /。
(
)
{
}
- 在实现临时值的 PR值表达式和引用的绑定之间应用任何操作。
- 使用除内置数组或 .
std::array
编译器(至少在过去)也存在错误,导致生存期扩展无法正确实现,因此实际上代码将再次具有未定义的行为。
取而代之的是,使用带有命名变量的原始方法,或者只是使用以下命令将对象直接放入数组中:std::variant
std::variant<Generate,Scan> App::commands[] {Generate(), Scan()};
更好的是,摆脱 App.cpp 并直接在 App.hpp 中定义命令
这是一个单独的问题,在 C++ 17 及更高版本中很容易:您只需要放入之前/之后,然后就可以在类中初始化静态数据成员,就像它在类外工作一样。inline
static
评论
run
string
run
static
inline static void(*commands[])(const vector<string>&) {Generate::run};