gpt4 book ai didi

c++ - 接口(interface)和协变问题

转载 作者:可可西里 更新时间:2023-11-01 18:26:50 25 4
gpt4 key购买 nike

我有一个特定的类来存储一段数据,它实现了一个接口(interface):

template<typename T>
class MyContainer : public Container<T> {
class Something : public IInterface {
public:
// implement *, ->, and ++ here but how?
private:
T x;
};

// implement begin and end here, but how?

private:
Something* data; // data holds the array of Somethings so that references to them can be returned from begin() and end() to items in this array so the interface will work, but this makes the problem described below
};

我有一个 Something 数组。

我需要Something 来实现接口(interface)类(示例中的IInterface):

  1. 包含纯虚拟成员函数,它返回一些东西,例如 *retval 返回对 x 成员的引用,retval-> 返回地址x++retval 使 retval 引用数组中的下一个 Something
  2. 纯虚成员返回的东西可以继承成员的实现并返回
  3. container[i](其中 container 是保存 Something 对象的数组)总是返回这样的东西 *retval 总是为相同的 i 返回对相同 T 的引用。

现在,界面看起来像这样:

template<typename T>
class Container {
class IInterface {
public:
virtual T& operator*() = 0;
virtual T* operator->() = 0;
virtual IInterface& operator++(); // this is the problem
};

// returning a reference right now to support covariance, so subclasses can
// derive from Container and then have a member class derive from IInterface
// and override these to return their derived class, but this has a problem
virtual IInterface& begin() = 0;
virtual IInterface& end() = 0;
};

我目前的解决方案(让虚方法返回一个IInterface&并在实现中返回一个Something&)没有问题,除了 满足 ++retval 要求。因为 Something 直接绑定(bind)到它所持有的对象,不能用指针指向 T,所以我无法找到 + + 使变量引用数组中的下一个 Something

如果有助于了解,这是一个迭代器类型系统。我会用 STL 风格的迭代器(你只有一个 T 的数组)实现它,它按值传递并保存指向它们所代表的值的指针,但这会破坏接口(interface),因为只有引用和指针是协变的,并且对象已经存在于其他地方(在我的代码中它们在数组中),因此您不会返回对本地对象的引用。

此设置的目的是让人们可以编写函数来获取 Container& 并在不知道容器是什么类型的情况下迭代容器:

void iterate(Container<int>& somecontainer) {
Container<int>::IIterator i = somecontainer.begin(); // right now this would return a reference, but it doesn't/can't work that way
while (i != somecontainer.end()) {
doSomething(*i);
++i; // this is the problem
}
}

这对我来说有点难以描述,如果您需要更多信息,请随时告诉我。

最佳答案

您尝试执行的操作称为类型删除。基本上,您想要提供一个值类型(在整个继承层次结构中都是相同的)来包装特定的迭代器类型并提供一个统一的动态接口(interface)。

类型删除通常使用非虚类(类型删除)实现,该类存储指向实现删除的虚基类的指针,您可以从中派生出包装每个特定迭代器的不同类型。静态类将提供模板化的构造函数/赋值运算符,它们将动态实例化派生类型的对象并在内部存储指针。然后你只需要将这组操作实现为对内部对象的分派(dispatch)。

对于最简单的类型删除形式,您可以查看 boost::any 的实现(文档为 here)

素描:

namespace detail {
template<typename T>
struct any_iterator_base {
virtual T* operator->() = 0; // Correct implementation of operator-> is tough!
virtual T& operator*() = 0;
virtual any_iterator_base& operator++() = 0;
};
template <typename T, typename Iterator>
class any_iterator_impl : any_iterator_base {
Iterator it;
public:
any_iterator_impl( Iterator it ) : it(it) {}
virtual T& operator*() {
return *it;
}
any_iterator_impl& operator++() {
++it;
return *this;
}
};
}
template <typename T>
class any_iterator {
detail::any_iterator_base<T>* it;
public:
template <typename Iterator>
any_iterator( Iterator it ) : it( new detail::any_iterator_impl<T,Iterator>(it) ) {}
~any_iterator() {
delete it;
}
// implement other constructors, including copy construction
// implement assignment!!! (Rule of the Three)
T& operator*() {
return *it; // virtual dispatch
}
};

实际的实现变得非常困惑。您需要为标准中的不同迭代器类型提供不同版本的迭代器,并且运算符的实现细节可能也不是微不足道的。特别是 operator-> 被迭代应用直到获得原始指针,并且您想确保您的类型删除行为不会破坏该不变量或记录您如何破坏它(即类型限制T 你的适配器可以包装)

扩展阅读: - On the Tension Between Object-Oriented and Generic Programming in C++ - any_iterator: Implementing Erasure for C++ iterators - adobe any_iterator ,

关于c++ - 接口(interface)和协变问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6977820/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com