拥有模板是指共同继承的类中的成员

时间:2015-01-28 16:40:07

标签: c++ templates multiple-inheritance

很明显,以下代码无法编译,因为它在'n = n_init'行给出了“未声明的标识符”错误。然而,对于一个人类读者来说,意图可能已经足够清楚了:我想为一个永远不会自己实例化的类声明一个模板,但只能通过多个继承和另一个类来保证,该类保证至少包含一个成员'n' int类型和类型为T *的成员'p',但是(从其他地方获得的C结构)我不能自由地从包含这些字段的另一个模板派生:

// In a C header file from elsewhere:
// ----------------------------------
typedef struct {
    float *p;
    int n;
} float_array_C;

// In my C++ header file:
// ----------------------

template<typename T> class MyArray
{
public:
    MyArray(int n_init)
    {
        n = n_init;   
        contents.resize(n);
        p = contents.data();
    }

    virtual void mustExist() = 0;

private:
    std::vector<T> contents; 
};


class float_array : public float_array_C, public MyArray<float>
{
public:
    float_array(int n) : float_array_C(), MyArray(n)
    {}

    virtual void mustExist() {}
};

...

float_array testArray(10);

我也试过这种方法,同样没那么成功:

typedef struct {
    float *p;
    int n;
} float_array_C;

template<typename T1, typename T2> class MyArray
{
public:
    MyArray(int n_init)
    {
        &T2::n = n_init;   
        contents.resize(n);
        &T2::p = contents.data();
    }

private:
    std::vector<T1> contents; 
};


typedef MyArray<float, float_array_C> floatArray;


...

float_array testArray(10);

事实上,这个或与它类似的任何东西都可以吗?

2 个答案:

答案 0 :(得分:1)

为了使其正常工作,模板类必须从包含n的类型派生,然后您可以T::n访问它,其中T是模板参数。

(您不能仅使用n访问继承的成员,因为它不是依赖名称,因此编译器将在编译模板时尝试解析它,而不是以后在实例化时,n或全局范围内不存在MyArray。使用T::n会使其成为依赖名称 - 取决于T - 并且因此,在实例化模板之前,将延迟解析名称。)

typedef struct {
    float *p;
    int n;
} float_array_C;

template <typename T>
class MyArray : public T
{
public:
    MyArray(int n_init) {
        T::n = n_init;
    }
};

请注意,您将遇到以下代码的问题:

class Foo : public float_array_C, public MyArray<float_array_C> { /* ... */ };

在这种情况下,FooMyArray<float_array_C>都包含单独的 float_array_C实例。如果这是一个问题,您可以对float_array_C使用虚拟继承:

template <typename T>
class MyArray : virtual public T { /* ... */ };

class Foo :
    virtual public float_array_C,
    public MyArray<float_array_C>
{ /* ... */ };

答案 1 :(得分:1)

另一种只需要一个模板参数的方法:

typedef struct {
    float *p;
    int n;
} float_array_C;

template<typename T> class MyArray : public T
{
public:
    MyArray(int n_init)
    {
        T::n = n_init;   
        contents.resize(T::n);
        T::p = contents.data();
    }       
private:
    std::vector<std::remove_pointer_t<decltype(T::p)>> contents;
};

typedef MyArray<float_array_C> floatArray;