C++是否支持抽象数组长度
Does C++ support abstract array lengths
如果我有一个基类A
,我希望能够在A
中编写代码,该代码使用由其子级确定大小的数组
我希望能够有一个指向A
的指针数组,但我不希望为每个长度的创建单独的成员函数
我能想出的最好的办法如下:
class A
{
char type;
int * values;
int calc(int pos); // implementation is not relevant to question
public:
A (int * arr) : values(arr) {}
int foo(int pos)
{
int index=calc(pos);
return values[index];
}
};
template <size_t X>
class B : public A
{
int vals[X];
public:
B() : A(vals) {}
};
template<>
class B<0>; // don't want 0 allowed
这允许A访问子级确定大小的数组,并且该数组是连续内存
但是,它浪费了values
指针的空间,并混淆了编译器可以用于优化的信息,因为在实现时,它不必是子级在构造时传递的连续内存,但我希望需要连续内存。
理想情况下,我想直接在A
中使用偏移
在C
中,这与int values[]
一样工作,但没有C++
等效的
可以,使用模板:
template<std::size_t size>
struct A {
A(std::array<int, size> _values) : values{_values} {}
private:
std::array<int, size> values;
};
struct B : A<4> {
using A<4>::A;
};
然后,你可以这样使用你的类:
B myB{5, 6, 3, 2};
std::array
在堆栈上或直接在结构中分配内存,就像固定数组一样。你可以通过比较尺寸来测试这一点。
如果你需要一个通用基类,你可以这样做:
struct C {
virtual ~C() {}
virtual int* data();
virtual std::size_t size();
};
然后在A
:中否决论文
template<std::size_t size>
struct A : C {
A(std::array<int, size> _values) : values{_values} {}
int* data() override {
return values.data();
}
std::size_t size() override {
return size;
}
private:
std::array<int, size> values;
};
实现这一点的经典方法是使用继承和虚拟成员:
class A {
virtual int& value_at(size_t pos);
// other interesting methods
};
// subclass of A that uses std::vector for storage
class B: public A {
std::vector<int> storage;
int& value_at(size_t pos) {
return storage[pos];
}
};
// subclass of A that uses a fixed-size array for storage
template<int N>
class C: public A {
int storage[N];
int& value_at(size_t pos) {
return storage[pos];
}
};
B b; // ...initialize b...
C<10> c; // ...initialize c...
A *a1 = &b;
A *a2 = &c;
// call a1->value_at(), a2->value_at() to access arrays
// transparently, regardless of storage (along with other
// public methods of A).
这种方法将要求A::value_at
通过虚拟表或等效机制进行调度。如果在编译时知道将使用哪种存储策略,则可以将A
作为模板类:
template<typename T>
class A: public T {
// other interesting methods, that use value_at() from T
};
class vec_storage {
std::vector<int> storage;
public:
int& value_at(size_t pos) {
return storage[pos];
}
};
// subclass of A that uses a fixed-size array for storage
template<int N>
class array_storage {
int storage[N];
public:
int& value_at(size_t pos) {
return storage[pos];
}
};
A<vec_storage> b;
A<array_storage<10>> c;
在本例中,b
和c
在运行时将在没有额外间接性的情况下执行,但代价是没有泛型基类,因此不能向期望某个A &
的函数传递对b
或c
的引用。
正如Fred Larson所指出的,为了获得更改对象数组大小的基本能力,您可能正在寻找模板。其实很简单。。。
template <const int arraySize>
class MyClass
{
private:
int vals[arraySize];
}
在这一点上,您甚至不需要任何派生类。您可以随时随地使用任何尺寸的。
但是,请记住,在这种情况下,MyClass
不是一个有效的类型。因为这是一个模板,所以必须指定大小。
MyClass wrong; //This will throw an error. MyClass is not a type.
MyClass<64> right; //This is a proper use of the type.
如果您需要存储不同大小的对象的额外功能,则可以使用虚拟的[但不是抽象的]基类将其与继承结合起来。
(请忽略这个糟糕的设计,因为我在这个例子中没有费心定义我的构造函数/析构函数。)
class BaseClass
{
public:
BaseClass(){}
virtual int access(int i)
{
return 0;
}
virtual ~BaseClass(){}
};
template <const int arraySize>
class MyClass : public BaseClass
{
public:
MyClass(){}
int access(int i)
{
return vals[i];
}
~MyClass(){}
private:
int vals[arraySize];
};
警告:如果您希望能够将派生类存储在向量中,则基不能是抽象的,这一点至关重要。请参阅此问题。
当然,在本例中,您可能希望创建用于访问数组的包装器函数。
- 指向抽象类的指针数组:指向 nullptr 或不指向 nullptr (C++)
- C++ 2D shared_ptr数组使用抽象多态类型初始化
- 基类为抽象的 ADT 数组
- 在C 中的数组中存储抽象基类的不同派生类的对象
- 使用数组时的抽象与性能
- 如何使用C样式在C 中正确复制抽象类数组的2D数组
- 抽象数据类型命名约定:(动态)数组,向量,序列,列表,容器,缓冲区
- 将派生对象添加到(抽象的)基指针数组中
- C++是否支持抽象数组长度
- 在C++中初始化抽象基类的子类数组
- 如何为抽象类创建二维数组
- 如何将抽象类型数组作为函数参数传递
- 指向抽象类的指针数组
- libpng 的C++抽象导致 malloc 崩溃 -- 删除 2D 数组"Jagged"
- 创建派生类对象的指针数组.C++抽象基类
- 如何使用抽象类的Polymorphy 2D数组进行创建
- 抽象类的2D数组
- C++将抽象对象存储在数组中
- 如何在c++中创建抽象类的数组
- c++函数在宏值上切换语句或数组抽象