[英]Is it alright to return a reference to a non-pointer member variable as a pointer?
[英]Covariant return type with non-pointer/reference return type
我正在尝试在C ++(11)中实现一个类似于集合类的.NET框架。 我的问题是无效的协变类型。 我有这些课:
template<typename T>
class IEnumerator
{
public:
virtual bool MoveNext() = 0;
//...
};
template<typename T>
class IEnumerable
{
virtual IEnumerator<T> GetEnumerator() = 0;
};
template<typename T>
class List : public IEnumerable<T>
{
public:
struct Enumerator : public IEnumerator<T>
{
Enumerator(List<T> &list)
{
//...
}
// ...
};
Enumerator GetEnumerator()
{
return Enumerator(*this);
}
};
据我说,这太棒了。 但是用C ++实现它似乎是不可能的。 我通过g ++获得了“无效的协变量返回类型”,据我所读,问题是GetEnumerator可能只返回一个指向Enumerator的指针或引用,而不返回Enumerator本身的对象。
我想避免返回这样的指针:
Enumerator *GetEnumerator()
{
return new Enumerator(*this);
}
因为我不希望呼叫者费心删除。 使用临时对象,我将确保该对象被自动删除,因为不再需要它。 使用引用可能会更糟。
我想念什么吗? 还是C ++标准(和语言)有一个巨大的漏洞? 我真的很想实现这样的目标。
提前致谢。
协变值返回类型无法实现。
问题是调用者有责任在堆栈中为返回的对象分配空间,并且在编译时返回协变量值所需的空间量将是未知的。
这与指针/引用无缝配合,因为返回的对象是指针或引用(而不是实际的派生对象),并且大小在编译时已知。
在与@curiousguy进行相当荒谬的(对我而言)讨论之后,我必须回溯先前的答案。 没有技术上的问题会使协变值返回类型成为不可能。 另一方面,它会产生不同的负面影响:
从设计的角度来看,如果从基础调用,则必须对返回的对象进行切片 (这是返回对象的大小所在)。 这与当前模型有明显的区别,在当前模型中,函数始终返回相同的对象,只有引用或指针会更改类型。 但是实际对象是相同的。
在一般情况下,协变量值类型会抑制某些复制删除优化。 当前,对于按值返回的函数,许多调用约定规定调用者将指针传递给返回对象的位置。 这样,调用方可以保留将保留该值的变量的空间,然后将其传递给指针。 然后,被调用方可以使用该指针来代替将在调用方上下文中保存该值的对象的构造,并且不需要任何副本。 使用协变量值返回的类型,并且由于必须破坏最终重写器创建的最派生对象,以避免未定义的行为。 调用者将指针传递到内存中的某个位置,蹦床函数将不得不为最终重写器的返回对象保留空间,然后它将需要从该第二个对象切片复制到第一个对象,从而产生一个复制。
无论如何,操作的实际成本将不是一个问题,因为对最终重写器的调用的语义会有所不同*这取决于执行调用所通过的引用的静态类型是什么。
*当前语言定义已经是这种情况。 对于所有非虚函数,如果派生类型在基础上隐藏了一个成员函数,则返回的指针/引用的静态类型(这又取决于用于调用虚函数的静态类型)将影响要获取的函数实际被调用,行为有所不同。
template<typename T>
class IEnumerable
{
virtual IEnumerator<T> GetEnumerator() = 0;
};
您正在尝试返回IEnumerable<T>
但这是一个抽象基类 :这意味着您承诺构造一个无法实例化的类的对象!
只能实例化派生自抽象基类的具体类 。
您可能打算返回一个指向此类对象的指针。 无论如何,这是不好的设计。 您无需在C ++中模拟Java。
除非使用指针,否则您不会在C ++中做类似的事情。 .net家伙使用引用,因此几乎是相同的东西。
在C ++中,您更有可能使用概念而非继承来实现。 您应该查看“通用编程”的想法。 Boost网站有一个不错的介绍: http : //www.boost.org/community/generic_programming.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.