通过强制父类引用子类来提供类的可迭代“视图”

时间:2013-11-25 22:40:27

标签: c++

我有一个类,有几种方法可以迭代它。例如,您可以迭代查看其中的所有ABC。该类没有虚函数。

我希望这些有一个很好的界面。我想知道以下是否给出了未定义或未指定的行为,或者是否可以这样做。

我正在考虑制作这个类的三个派生类:

// can look at this in three ways
struct myClass {
    void myFunc();
};

struct A_view : public myClass {
    A_iterator begin();
};

struct B_view : public myClass {
    B_iterator begin();
};


struct C_view : public myClass {
    C_iterator begin();
};

然后

A_view& get_C_view(const myClass& c) {
    return *reinterpret_cast<B_view*>(&c);
}

B_view& get_B_view(const myClass& c) {
    return *reinterpret_cast<B_view*>(&c);
}

C_view& get_C_view(const myClass& c) {
    return *static_cast<C_view*>(&c);
}

我希望能够像

一样使用它
myClass inst;

for (auto& c : get_C_view(inst))
    //stuff

for (auto& b : get_B_view(inst))
    //stuff

auto& bview  = get_b_view(inst);

std::transform(bview.begin(), bview.end(), bview.begin(), [](auto& x, auto& y) { /* smthing */ });

bview.myFunc();

或来自<algorithm>的算法。如您所见,您还可以使用视图上父类中定义的函数。

所以,我正在将一个实例转换为对从它派生的类型的引用,它只添加函数,而不是数据,但它实际上并不是这些类型之一。

这可以吗? “ok”我的意思是

  1. 这是明确定义,未定义或未指定的行为吗?
  2. 如果没有明确定义,这会在实践中引起问题吗?
  3. Herb Sutter会皱眉吗?

1 个答案:

答案 0 :(得分:3)

由于多种原因,继承不是在这种情况下使用的正确工具,第一个是你不能将对象强制转换为它不是的类型,但更普遍的是因为继承是第二个最高的耦合关系。语言,应谨慎使用(即需要时,不仅仅是因为)。

您可以创建包含对类型的引用的瘦包装类型,并将其开始/结束函数映射到组件上的相应视图:

struct C_view {
   MyClass &obj;
   C_view(MyClass& obj) : obj(obj) {}
   C_iterator begin() {
     return obj.c_begin();
   }
   C_iterator end() {
     return obj.c_end();
   }
};

然后用户代码变为:

for (auto &c : C_view(inst)) {
   ...
}