返回对象时如何更改返回对象基类函数的实现 C++
我有一个现有的 C++ 应用程序,其中包含一个自定义 ArrayBase 类,该类管理存储和对连续分配的内存区域的访问。我有一个单独的 ItrBase 类,用于访问该 ArrayBase 中的数据。 ArrayBase
有一个 createItr()
函数,当前返回一个 ItrBase
对象。
我需要扩展 ArrayBase 以使用多个内存分配而不是一个连续的内存分配。我创建了一个EnhancedArray 类来执行此操作。为了使此 EnhancedArray 与现有应用程序兼容,它的 createItr() 函数必须返回适用于新的多个内存分配的内容。
因此,我创建了一个派生的 EnhanceItr 类来执行此操作。 我的问题是我无法找到一种方法来处理数百个这样的代码:
ItrBase anIterator = anArray.createItr();
...
double x = anIterator.getData();
在 anArray
时使用 EhancedItr
的 getData()
函数code> 是一个 EnhancedArray
。
这是一个简单的应用程序,说明了我的基本安排。
#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;
}
当我希望第二个调用返回 0 时,上面对 vfunc()
的两次调用都返回 1。
在 main()
中,我知道如果我更改 ItrBase
类型转换为 ItrBase &
's,我确实得到了所需的返回类型,但随后我在数百个区域修改了我的“现有”代码,并且迭代器的析构函数不是叫。
还有其他我没有看到的策略吗?
谢谢。
I have an existing application in C++ with a custom ArrayBase
class that manages storage and access to a contiguously allocated region of memory. I have a separate ItrBase
class that is used to access data in that ArrayBase
. ArrayBase
has a createItr()
function that currently returns an ItrBase
object.
I need to extend ArrayBase
to use multiple memory allocations instead of one contiguous one. I have created an EnhancedArray
class to do that. For this EnhancedArray
to be compatible with the existing application, it's createItr()
function must return something that works with the new multiple memory allocations.
So, I have created a derived EnhanceItr
class to do this.
My problem is I can't figure out a way for hundreds of code occurrences like this:
ItrBase anIterator = anArray.createItr();
...
double x = anIterator.getData();
to use the EhancedItr
's getData()
function when anArray
is an EnhancedArray
.
Here is a simple application illustrating my basic arrangement.
#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;
}
Both calls to vfunc()
above return 1, when I want the second call to return 0.
In main()
, I know that if I change the ItrBase
types to ItrBase &
's, I do get the desired return types, but then I am modifying my 'existing' code in hundreds of areas, and the destructors for the Iterators are not called.
Is there another strategy that I am not seeing?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
当然,如果您被允许重写
ItrBase
,那么您可以使用委托将所有函数调用传递给实现类,您通过指针或引用保存该实现类,以便多态性生效。这看起来很像pimpl。并且调用者根本不需要编写,只需重新编译即可。编辑:为那些不熟悉 pimpl 的人提供的代码。
Sure, if you're allowed to rewrite
ItrBase
, then you can use delegation to pass all function calls through to an implementation class, which you hold by pointer or reference so that polymorphism is in effect. This would look a lot like pimpl. And the callers would not have to be written at all, only recompiled.EDIT: code for those not familiar with pimpl.
您遇到了一个名为切片:
createItr
返回一个引用,然后将其复制到ItrBase
按值。就好像您做了这样的事情:您还泄漏了内存:
createItr
返回一个新分配的对象,但您从未删除它。这是非常糟糕的,特别是因为您希望频繁使用数组迭代器。You're running into a problem called slicing:
createItr
returns a reference, and then you're copying that into anItrBase
by-value. It's as if you did something like this:You're also leaking memory:
createItr
returns a newly allocated object, but you're never deleting it. This is very bad, especially since you'd expect array iterators to be used frequently.您可以做的完全不同的事情是使用,
并让编译器计算出返回类型。
BOOST_AUTO
completely different thing you can do is use,
and let compiler figure out return type.
BOOST_AUTO
由于没有及时更新标准库,我无法使用 Ben Voigt 建议的
unique_ptr
实现。 (版本> = 4.3)我相信我已经采用了他的概念并用基本指针实现了它。但请注意,此实现不是异常安全的。ItrImpl
对象可以保留不删除。这是我的代码。太糟糕了
createItr()
必须返回ItrBase
对象而不是指针,否则我认为我可以让auto_ptr
工作。程序执行期间的输出显示,每个实例仅调用~ItrBase()
一次,但令我惊讶的是,在从createItr()
返回对象期间,它也没有被调用。返回值优化?Not being up-to-date with the Standard Library, I could not use the
unique_ptr<>
implementation suggested by Ben Voigt. (version >=4.3) I believe I have taken his concept and implemented it with basic pointers instead. Noting, however, that this implementation is not exception-safe.ItrImpl
objects could be left undeleted.Here's my code. Too bad
createItr()
has to return aItrBase
object rather than a pointer, otherwise I think I could have gottenauto_ptr<>
to work. Output during program execution shows that~ItrBase()
is called only once for each instance, but I am suprised it is not called also during the object return fromcreateItr()
. Return value optimization?