我在C ++中有一个现有的应用程序,它有一个自定义ArrayBase
类,用于管理存储和访问连续分配的内存区域。我有一个单独的ItrBase
类,用于访问ArrayBase
中的数据。 ArrayBase
有一个createItr()
函数,当前返回ItrBase
个对象。
我需要扩展ArrayBase
以使用多个内存分配而不是一个连续内存分配。我创建了一个EnhancedArray
类来做到这一点。为使此EnhancedArray
与现有应用程序兼容,它的createItr()
函数必须返回适用于新的多内存分配的内容。
所以,我已经创建了一个派生的EnhanceItr
类来执行此操作。
我的问题是我无法找到像这样的数百个代码出现的方法:
ItrBase anIterator = anArray.createItr();
...
double x = anIterator.getData();
在EhancedItr
为getData()
时使用anArray
的{{1}}功能。
这是一个简单的应用程序,说明了我的基本安排。
EnhancedArray
当我希望第二次调用返回0时,对#include <iostream>
using namespace std;
class ItrBase {
public:
ItrBase() { cout << "ItrBase constructor.\n"; };
~ItrBase() { cout << "ItrBase destructor.\n"; };
virtual int vfunc() {return 1;};
};
class EnhancedItr : public ItrBase {
public:
EnhancedItr() { cout << "EnhancedItr constructor.\n"; };
~EnhancedItr() { cout << "EnhancedItr destructor.\n"; };
int vfunc() {return 0;};
};
class ArrayBase {
public:
ArrayBase() { cout << "ArrayBase constructor.\n"; };
~ArrayBase() { cout << "ArrayBase destructor.\n"; };
virtual ItrBase & createItr() {cout << "in AB's createItr()\n"; return *new ItrBase(); };
};
class EnhancedArray : public ArrayBase {
public:
EnhancedArray() { cout << "EnhancedArray constructor.\n"; };
~EnhancedArray() { cout << "EnhancedArray destructor.\n"; };
EnhancedItr & createItr() {cout << "in EA's createItr()\n"; return *new EnhancedItr(); };
};
int main()
{
ArrayBase ab;
EnhancedArray ea;
ItrBase itr = ab.createItr();
ItrBase eitr = ea.createItr(); //EnhancedItr assigned to ItrBase
cout << "ArrayBase's Itr .vfunc(): " << itr.vfunc() <<std::endl;
cout << "EnhancedArray's Itr .vfunc(): " << eitr.vfunc() <<std::endl;
return 0;
}
的两次调用都返回1。
在vfunc()
中,我知道如果我将main()
类型更改为ItrBase
,我会获得所需的返回类型,但之后我正在修改“现有”代码在数百个区域中,并没有调用迭代器的析构函数。
我还没有看到另一种策略吗?
感谢。
答案 0 :(得分:2)
当然,如果允许您重写ItrBase
,那么您可以使用委托将所有函数调用传递给实现类,该实现类由指针或引用保存,以便多态性生效。这看起来很像 pimpl 。并且根本不需要编写调用者,只需重新编译。
编辑:那些不熟悉pimpl的人的代码。
struct ItrBase
{
struct ItrImpl
{
virtual ~ItrImpl(){}
virtual int vfunc() = 0;
};
ItrBase(ItrImpl peer) : m_peer(peer) { cout << "ItrBase constructor.\n"; }
~ItrBase() { cout << "ItrBase destructor.\n"; }
int vfunc() { return m_peer->vfunc(); }
private:
const unique_ptr<ItrImpl> m_peer;
};
class ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() { return 0; }
};
public:
ArrayBase() { cout << "ArrayBase constructor.\n"; };
~ArrayBase() { cout << "ArrayBase destructor.\n"; };
virtual ItrBase createItr() { cout << "in AB's createItr()\n"; return ItrBase(new ItrImpl); };
};
class EnhancedArray : public ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() { return 1; }
};
public:
EnhancedArray() { cout << "EnhancedArray constructor.\n"; };
~EnhancedArray() { cout << "EnhancedArray destructor.\n"; };
virtual ItrBase createItr() { cout << "in EA's createItr()\n"; return ItrBase(new ItrImpl); };
};
答案 1 :(得分:0)
您遇到了一个名为slicing的问题:createItr
会返回一个引用,然后您将其复制到ItrBase
按值 。就像你做了这样的事情:
EnhancedItr itr1 = ...;
BaseItr itr2 = itr1; // copy by-value
cout << itr2.vfunc(); // prints 1, not 0
你也在泄漏内存:createItr
返回一个新分配的对象,但你永远不会删除它。这非常糟糕,特别是因为您希望频繁使用数组迭代器。
答案 2 :(得分:0)
答案 3 :(得分:0)
不与标准库保持同步,我无法使用Ben Voigt建议的unique_ptr<>
实施。 (版本&gt; = 4.3)我相信我已经采用了他的概念并用基本指针实现了它。但请注意,此实现不是异常安全的。 ItrImpl
个对象可能会被取消删除。
这是我的代码。太糟糕了createItr()
必须返回ItrBase
对象而不是指针,否则我认为我可以让auto_ptr<>
工作。程序执行期间的输出显示~ItrBase()
仅为每个实例调用一次,但我很惊讶在从createItr()
返回对象期间也没有调用它。返回值优化?
#include <iostream>
using namespace std;
struct ItrBase
{
struct ItrImpl
{
virtual ~ItrImpl(){};
virtual int vfunc() const = 0;
};
ItrBase(ItrImpl* peer) : m_peer(peer) { cout << "ItrBase constructor.\n"; };
~ItrBase() { cout << "ItrBase destructor. \n"; delete m_peer; };
int getData() const { return m_peer->vfunc(); };
private:
ItrImpl* const m_peer;
};
class ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() const { return 0; };
};
public:
ArrayBase() { cout << "ArrayBase constructor.\n"; };
~ArrayBase() { cout << "ArrayBase destructor.\n"; };
virtual ItrBase createItr() { cout << "in AB's createItr()\n"; return ItrBase(new ItrImpl); };
};
class EnhancedArray : public ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() const { return 1; };
};
public:
EnhancedArray() { cout << "EnhancedArray constructor.\n"; };
~EnhancedArray() { cout << "EnhancedArray destructor.\n"; };
virtual ItrBase createItr() { cout << "in EA's createItr()\n"; return ItrBase(new ItrImpl); };
};
int main()
{
ArrayBase ab;
EnhancedArray ea;
ItrBase itr = ab.createItr();
ItrBase eitr = ea.createItr(); //EnhancedItr assigned to ItrBase
cout << "ArrayBase's Itr .vfunc(): " << itr.getData() <<std::endl;
cout << "EnhancedArray's Itr .vfunc(): " << eitr.getData() <<std::endl;
return 0;
}