operator++(int)重载抽象基类和Wall
operator++(int) overload with abstract base class and Wall
我目前正在创建一组迭代器,它们将在实现细节上有所不同,但将在相同的算法中使用。因此,它们都必须具有相同的接口。为了实现这一点,我创建了一个抽象迭代器类,并在所有后续迭代器中继承这个类。
这应该能让你了解我的代码是什么样子的:
class INodeIterator
{
public:
virtual ~INodeIterator() {};
virtual bool operator!= (const INodeIterator& other) =0;
virtual bool operator== (const INodeIterator& other) =0;
virtual INodeIterator& operator++ () =0;
virtual INodeIterator& operator++ (int i) =0;
virtual Node& operator* () =0;
};
class NodeIterator : public INodeIterator
{
public:
/* snip */
NodeIterator& operator++ (int i)
{
NodeIterator tmp(*this);
++(*this);
return(tmp);
}
};
现在我面临着与在迭代器中c++后增量操作符重载相同的问题(使用-Wall -Werror编译):我的operator++(int)实现抛出一个警告(gcc 4.8.0),返回对临时对象的引用。链接问题的解决方案是只返回对象而不是引用。
然而,这对我不起作用。如果我更改接口和派生类以返回对象而不是引用,则会出现以下错误(删除摘录,附加文件名等):
INodeIterator.h:16:27: error: invalid abstract return type for member function ‘virtual INodeIterator INodeIterator::operator++(int)’
virtual INodeIterator operator++ (int i) =0;
^
NodeIterator.h:33:22: error: invalid covariant return type for ‘virtual NodeIterator NodeIterator::operator++(int)’
NodeIterator operator++ (int i);
^
INodeIterator.h:16:27: error: overriding ‘virtual INodeIterator INodeIterator::operator++(int)’
virtual INodeIterator operator++ (int i) =0;
^
在派生类而不是抽象类上更改返回类型为object,预计会返回"指定的返回类型冲突"错误。
我怎样才能使它工作?
尝试改变设计:让我们的NodeIterator保存INodeIterator作为一个指针。NoteIterator的所有方法都将委托给持有INodeIterator对象。在这种情况下,您可以使用正确的签名:
struct IteratorInterface {
virtual ~IteratorInterface() {}
virtual std::unique_ptr<IteratorInterface> clone() const = 0;
virtual void next() = 0;
};
class Iterator {
std::unique_ptr<IteratorInterface> impl;
public:
Iterator(std::unique_ptr<IteratorInterface> r) : impl(std::move(r)) {}
Iterator(const Iterator &r) : impl(r.impl->clone()) {}
Iterator& operator++() {
impl->next();
return *this;
}
Iterator operator++(int ) {
Iterator tmp(*this);
impl->next();
return tmp;
}
void swap(Iterator &other) {
other.impl.swap(impl);
}
};
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
struct IteratorInterfaceImpl : IteratorInterface {
int i;
IteratorInterfaceImpl() : i(0) {}
virtual std::unique_ptr<IteratorInterface> clone() const {
return std::unique_ptr<IteratorInterface>(new IteratorInterfaceImpl(*this));
}
virtual void next() {
i += 1;
}
};
Iterator tmp(std::unique_ptr<IteratorInterface>(new IteratorInterfaceImpl()));
tmp++;
++tmp;
return 0;
}
我能想到的唯一相同的方法是从INodeIterator::operator++(int)
返回void
-即什么也不返回。
不能从自增后操作符返回引用,因为必须创建一个返回引用的实际对象(存储前一个值)。这个对象要么是动态分配的,必须被销毁(必须在返回的引用上显式调用delete
),要么是operator++(int)
的"局部变量",将在返回之前被销毁:
virtual NodeIterator& operator++(int)
{
NodeIterator prev_value(*this);
++(*this);
return prev_value; // dangling/invalid reference, `prev_value` is destroyed
}
virtual NodeIterator& operator++(int)
{
NodeIterator* pPrev_value = new NodeIterator(*this);
++(*this);
return *pPrev_value; // have to explicitly call delete on the returned ref...
}
你也不能从INodeIterator::operator++(int)
返回INodeIterator
类型的对象,因为它是一个抽象类。
出现错误的原因
INodeIterator.h:16:27: error: invalid abstract return type for member function ‘virtual INodeIterator INodeIterator::operator++(int)’
virtual INodeIterator operator++ (int i) =0;
是因为你的纯虚函数返回一个抽象类对象。
一种解决方案是使用new操作符并返回在堆中创建的对象,这是安全的。
virtual INodeIterator& operator++ (int i) =0;
NodeIterator& operator++ (int i)
{
NodeIterator* tmp = new NodeIterator (*this);
++(*this);
return(*tmp);
}
你的原型不正确。应该是
NodeIterator operator++ (int i)
也就是说,放弃引用返回,否则您将返回对超出作用域(您的tmp
)的东西的引用。这不是一个好主意!
编译器在让你知道这一点上非常有帮助!
我知道这不是你想听到的
- std::具有相同基类的类的变体
- 是否可以初始化不可复制类型的成员变量(或基类)
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 基类中的函数名称解析
- C++初始化基类
- 如何通过派生类函数更改基类中的向量
- 如何定义一个纯抽象基类
- 如何使用基类指针引用派生类成员
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 使用基类指针创建对象时,缺少派生类析构函数
- 如何引用基类的派生类?
- 如果基类包含双指针成员,则派生类的构造函数
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 为什么此派生对象无法访问基类的后递减方法?
- 公开最直接的基类模板名称
- 当基类是依赖类型时,这是一个缺陷吗
- 如何使基类的运算符对基类的可变参数数可见(请参阅下面的代码)?
- 模板基类中的静态变量
- C++ 继承:将子类传递给需要基类的函数并获取子类行为
- operator++(int)重载抽象基类和Wall