【发布时间】:2011-10-22 02:41:30
【问题描述】:
我有一个特定的类来存储一段数据,它实现了一个接口:
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
};
我有一个Somethings 数组。
我需要Something 来实现一个接口类(示例中为IInterface):
- 包含纯虚成员函数,这些函数返回的内容使得
*retval返回对x成员的引用,retval->返回x的地址,而++retval使retval指向下一个@ 987654331@ 在数组中。 - 纯虚成员返回的东西可以从成员的实现继承和返回
-
container[i](其中container是包含Something对象的数组)总是返回这样的东西,*retval总是返回对相同T的引用,用于相同的i。
现在,界面是这样的:
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 直接绑定到它持有的对象并且不能用指针指向T,所以我无法找到++ 以使变量引用下一个Something在数组中。
如果有帮助的话,这是一个迭代器类型系统。我会使用 STL 风格的迭代器(你只有一个 T 的数组)来实现它,它们按值传递并保存指向它们所代表的值的指针,但这会破坏接口,因为只有引用和指针是协变的,并且对象必须已经存在于其他地方(在我的代码中它们位于数组中),因此您不会返回对本地对象的引用。
这种设置的目的是让人们可以编写函数来接受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
}
}
这对我来说有点难以描述,如果您需要更多信息,请随时告诉我。
【问题讨论】:
-
+1,你也可以提供一些关于
IInterface的代码,以及与++retval相关的方法在类中的样子。 -
@iammilind,我很乐意提供我能提供的任何信息,但是“与
++retval相关的方法在课堂上的表现如何”是什么?看看我的更新是不是你的意思。 -
@Cat 这样人们就可以在不知道容器类型的情况下编写采用
Container&的函数,并调用container.begin()来获取IInterface&并遍历容器的元素. -
T有什么限制?T可以是任何类型吗?如果是这样,您将不得不使用类似boost::any的东西来破解它,在这种情况下,该类的用户需要知道*container.begin()的类型是什么。不过,听起来您确实想要一个模板。 -
@Nicol:我不同意忽略差异。虽然模板多态性很棒,但它并不是唯一的一种。事实上,我有时会发现自己想要一个更少依赖模板的标准库,而更多地依赖于类层次结构来实现多态行为。有时,忽略差异确实是有意义的。事实上,如果不忽略实现细节,还有什么其他原因可以拥有抽象类之类的东西(真的,拥有类层次结构还有什么其他原因?)。
标签: c++ interface iterator covariance