在C ++中,您可以在文件范围内声明某个数组:
static foo a[] = { foo(), foo(), foo() };
各个foo对象具有静态存储(即它们不会在运行时分配)。
如果我有一个由两个或多个派生类继承的基类,则由于切片,以下内容会编译但不能按预期工作:
static base a[] = { derived1(), derived2() };
这样的事情不会导致切片发生:
static derived1 d1;
static derived2 d2;
static base *a[] = { &d1, &d2 };
我的问题是:如何在不必d1
与d2
分别声明a
和static base *a[] = { &derived1(), &derived2() };
的情况下,同时为个别(指向)元素保留静态存储空间?以下给出了临时"的地址。错误:
constexpr
也许可以定义一个template<typename... Args>
constexpr std::initializer_list<base *> base_array(Args... args) {
...
}
可变参数模板函数?类似的东西:
static base *a[] = base_ptr_array(derived1(), derived2());
然后我可以写:
{ foo(), foo(), foo() }
也许这会有相同的&#34;获取临时&#34;问题,虽然我的想法是因为这是一个constexpr,它的工作方式与上面的CONSTRAINT FOREIGN KEY(fk_EmployeeEmpID) REFERENCES Employee(EmpID)
类似(不会创建临时工具)。
答案 0 :(得分:7)
您可以使用某些模板来避免声明这些静态变量:
#include <tuple>
#include <array>
#include <type_traits>
#include <utility>
template<class Base, class... Ts>
struct foo {
foo()
: foo(Ts{}..., std::index_sequence_for<Ts...>{})
{}
std::tuple<Ts...> deriveds;
std::array<Base*, sizeof...(Ts)> arr;
private:
template<std::size_t... Is>
foo(Ts... ts, std::index_sequence<Is...>)
: deriveds(ts...)
, arr{ &std::get<Is>(deriveds)...}
{}
};
// test
#include <iostream>
struct A {
virtual void show() const {
std::cout << "A\n";
}
virtual ~A() = default;
};
struct B: public A
{
void show() const override {
std::cout << "B\n";
}
};
struct C: public A
{
void show() const override {
std::cout << "C\n";
}
};
foo<A, A, B, C> f;
int main() {
for ( A *ptr : f.arr ) {
ptr->show();
}
}
答案 1 :(得分:6)
老实说,我认为你正在尝试使用错误的工具来完成工作。以下是我的看法:
这是&#34;关闭集&#34;多态性给我。你可以在c++17中没有动态分配的情况下完成它。你甚至不需要这些类有一个共同的基类。只有你想要打电话的成员。所需要的只是std::variant
类型和一系列变体:
using variant_type = std::variant<derived1, derived2, ..., derived_n>;
static variant_type a[] = {
derived1(), derived2(), ..., derived_n()
};
你有它。你得到了多态行为,只需要std::visit
一个数组元素而不是通过指针调用成员函数:
for(auto& v : a)
std::visit([](auto& e) {
// Do something with e
// It's a reference to one of the types the variant can hold
}, v);