在C ++中为Parent类数据数组提供别名

时间:2017-10-05 18:23:45

标签: c++ c++11

可能不是最明智的选择,而是将Vertex<T, N>类建模为抽象Vertex2<T>Vertex3<T>Vertex4<T>实现,提供基本访问。它的结构如下:

template<typename T, unsigned N>
class _Vertex {
    const unsigned _size = N;
    T _data[N];

public:
    inline _Vertex() : _data() {};

    inline T const& operator[](int pos) const { return _data[pos]; } 
    inline T      & operator[](int pos)       { return _data[pos]; }
};

假设我想将Vertex2<T>实现为Vertex<T, 2>,并提供xy等别名。最合适的方法是添加以下功能:

 inline T const& x() const { return (*this)[0]; }
 inline T      & x()       { return (*this)[0]; }

对于我想要添加的每个属性或别名,都会重复此操作。这不是一个糟糕的设计,但用法证明是棘手的,因为v类型为Vector2<float>v.x() = 1.0f不如v.x = 1.0f友好。

有没有办法提供更清晰,更友好的别名?

我的主要想法是“滥用”内存布局,相应地提供对_data[i]的访问权限,但我不知道从哪里开始。

这个问题是基于我为一个分配提供的vertex.h头文件的“重新想象”,因此这与家庭作业有关,但我可以向你保证最终不会。这只是我的好奇心让我不做功课!

2 个答案:

答案 0 :(得分:1)

我穿上我的长袍和Yakk帽子。

operator->*在C ++中显然未被充分利用。我们可以重载以我们选择的标记类型,使其看起来像成员访问。这是一个简化的例子:

template <size_t I> struct index_t { };
constexpr index_t<0> x{};
constexpr index_t<1> y{};

struct Vector {
    int data[2];

    template <size_t I>        
    int& operator->*(index_t<I> ) { return data[I]; }

    int& operator[](size_t idx) { return data[idx]; }
};

有了这个,我们可以做到:

int main()
{
    Vector v{1, 2};
    std::cout << v.data[0] << ' ' << v.data[1] << '\n'; // 1 2
    v->*x = 42;
    v->*y = 17;
    std::cout << v.data[0] << ' ' << v.data[1] << '\n'; // 42 17
}

那就是说,不要这样做。 C ++没有属性。执行此操作的正确方法只是命名返回左值引用的函数:

int& x();
int& y();

它可能不像v.x那样“好”,但它可以完成工作,而无需在课程中添加额外的成员。

答案 1 :(得分:0)

v.x = 2.f不是OOP / C ++成员访问方式。最好使用像t = v.x()v.x( t )这样的get / set函数。

可以使用以下方法来破坏数据封装:

template< class T >
class Vertex2 : private Vertex< T, 2 >
{
public:
   T & x;
   T & y;
   Vertex2(): Vertex< T, 2 >(), x((*this)[0]), y((*this)[1]) {}
};

这不提供const访问权限,但如果你想v.x =,你可能不太关心这些事情。不幸的是,你可能会被两个引用的额外内存所困扰。