0

我有一个抽象基类,它包含一个数组以及两个或多个继承的类,它们希望在基类中有一个稍大的数组。

我试图通过使用模板来解决这个问题:

template <int arraySize>
class Baseclass {
public:
    uint16_t arr[arraySize];
};

class InheritedClass :
    public Baseclass <5> {};

我现在面临的问题是:每当我使用指向某个基类对象的指针时,编译器都会抱怨:

缺少类模板“Baseclass”的参数列表

我想我明白这里发生了什么:没有模板参数的基类现在不是一个完整的类型 - 但是编译器需要一个。

因此我想知道 - 是否有一种(更好的)方法来实现我想要做的事情,而不是在 InheritedClass 中分配数组并将指针向下传递给 Baseclass?

先感谢您!

4

5 回答 5

4

如果数组直接嵌入到基类中,如您的示例所示,则无法指定该数组的大小。更准确地说,更改该数组的大小将需要为每个特定数组大小生成该基类的完全不同版本。这将破坏目的,因为您的意图显然是在层次结构中拥有一个公共基类。是吗?

这正是您在使用模板“解决方案”时遇到的问题。您的程序不再有共同点Baseclass。相反,您拥有Baseclass<5>,Baseclass<10>等等 - 所有完全不同的独立基类。显然,这不是您所需要的。

实现具有运行时大小数组的公共基类的唯一方法是将数组间接存储在基类中。即在基类中声明一个uint16_t *指针并在运行时分配适当数量的内存。或者您可以简单地使用std::vector<uint16_t>而不是原始数组。

请注意,如果您决定采用指针方式,则并非绝对需要动态分配数组内存。您可以简单地使实际的“数组内存”成为已经“知道”特定大小的派生类的成员

class Baseclass {
public:
  uint16_t *arr;
  size_t arraySize;

  Baseclass(uint16_t *arr, size_t arraySize) : arr(arr), arraySize(arraySize)
    {}
};

class InheritedClass : public Baseclass
{
  InheritedClass() : Baseclass(arr_memory, 5)
    {}
private:
  uint16_t arr_memory[5];
};

因此,底线是,如果您希望将数组内存管理完全封装到Baseclass中,那么您别无选择,只能在运行时动态分配内存。如果这是不可接受的,那么您将被限制在其他地方执行内存管理并将其Baseclass从外部传递给它。

于 2013-10-26T20:12:09.710 回答
1

作为一种可能会起作用的技巧,在 .s 中包含一个baseclass方法。reinterpret_castthisbaseclass<1>

这依赖于您的 ty0es 被编译成相对健全的布局:为了鼓励这种情况发生,请确保baseclass至少是 pod 或标准布局。

虽然结果是未定义的行为,但在我使用的每个编译器中它都可以工作。

不足之处?你的数组有多大必须并行传输,并且你在运行时数组的大小上对你的类的其他用户撒谎。另外它非常脆弱:数组必须是baseclass.

您最好取消编译时静态边界,并std::vector使用运行时边界存储 a,因为这将避免未定义的行为黑客并减少每行代码的谎言。

于 2013-10-26T21:18:15.527 回答
1

您可以Baseclass从非模板类派生,并使用指向该类的指针。

于 2013-10-26T20:07:02.270 回答
0
class Baseclass {
public:
    uint16_t *arr;
    Baseclass(int arrlen) {
        arr = new int[arrlen];
    }

    ~Baseclass() {
        delete arr;
    }

};

class InheritedClass :
    public Baseclass {
public:
    Inherited() : Baseclass(5){
    }
};

如果可以,您可以简单地使用动态分配。

于 2013-10-26T20:11:51.620 回答
0

如果显式指定参数,C++ 将忽略默认表达式。因此,在您的派生类中,您明确指定CRTP的基类需求,但在基类中,您还提供一个默认值计算,以(仅)在实例化后使用。所以:

#include <iostream>
// instantiation specifies size explicitly, default calculation ignored
// after instantiation names in default calculation are bound correctly

template<class d,int size=sizeof d::m2/sizeof *d::m2>
struct b {
        int m[size];
};

struct d: b<d,20> {
        double m2[20];
};

int main() {
        std::cout<<sizeof b<d>::m/sizeof *b<d>::m<<'\n';
}
于 2013-10-26T23:54:58.767 回答