gpt4 book ai didi

c++ - 为类存储指向另一个类的指针复制构造函数析构函数和赋值运算符

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:45:01 25 4
gpt4 key购买 nike

我是新来的,这是我的第一个问题。我对我的家庭作业有疑问。我被要求设计一个抽象类“Base”,它由类“Sub”继承(在作业中有 sub1、sub2 等,但我试图尽可能地缩小它的范围)。然后,我应该设计一个类“BasePtr”,它存储一个指向“Base”对象的指针。最后,baseptr:s 将存储在 std::vector 中,并使用 ostream_iterator 和复制写入文件。然后应使用 ifstream_iterator 读取该文件,并将其存储在 std::list 中。

我已经解决了上述问题,但在实现析构函数、复制构造函数和赋值运算符时遇到了一些问题(因为我在我的 BasePtr 类中动态分配内存,我相信这些应该存在)。

这是主程序。

#include <vector>
#include <fstream>
#include <iterator>
#include <list>
#include "baseptr.h"

using namespace std;
int main()
{
vector<BasePtr> basevec;
basevec.push_back( BasePtr(new Sub(1, 4)) );
basevec.push_back( BasePtr(new Sub(3, 5)) );

ofstream os("fil.dat");
ostream_iterator<BasePtr> baseout(os,"\n");
copy( basevec.begin(), basevec.end(), baseout);
os.close();

ifstream is("fil.dat");
istream_iterator<BasePtr> basein(is), endofbasein;
list<BasePtr> baselist(basein, endofbasein );

for (list<BasePtr>::iterator it = baselist.begin(); it != baselist.end(); it++)
cout << *it << endl;
}

BasePtr 类

#include <iostream>
#include <string>
#include "base.h"

using namespace std;

class BasePtr {
public:
BasePtr() : basevar(0) {}
BasePtr(Base *bin) {basevar = bin->clone(); delete bin;}
const BasePtr & operator=( BasePtr & baseptr ); // assignment operator
BasePtr(const BasePtr &baseptr ); // copy constructor
~BasePtr(); // destructor
friend ostream& operator<<( ostream &os, const BasePtr &baseptr);
friend istream& operator>>( istream &is, BasePtr &baseptr);
private:
Base* basevar;
};

const BasePtr & BasePtr::operator=( BasePtr & baseptr ) {
if (this != &baseptr) {
delete basevar;
basevar = baseptr.basevar->clone();
}
return *this;
}

BasePtr::BasePtr( const BasePtr &baseptr ) {
if (baseptr.basevar != 0)
basevar = baseptr.basevar->clone();
}

BasePtr::~BasePtr() {
if ( basevar != 0 )
delete basevar;
basevar = 0;
}

ostream& operator<<( ostream &os, const BasePtr &baseptr) {
os << *baseptr.basevar;
return os;
}

istream& operator>>( istream &is, BasePtr &baseptr) {
string name;
if (!(is >> name))
return is;
Base *b = 0;
if ( name == "SUB" )
b = new Sub();
is >> *b;
baseptr.basevar = b->clone();
delete b;
return is;
}

以及基类和子类

#include <iostream>
using namespace std;

class Base {
public:
virtual ~Base() {}
virtual Base* clone() const = 0;
friend ostream& operator<<( ostream &os, Base &b) {
b.print(os);
return os;}
friend istream& operator>>( istream &is, Base &b) {b.readStream(is); return is;}
protected:
Base(const double xin) : x(xin) {}
double x;
virtual ostream& print(ostream &os) const = 0;
virtual void readStream( istream &is ) = 0;

};


class Sub : public Base{
public:
Sub() : Base(0), size(0) {}
Sub(double xin, double si) : Base(xin), size(si) {}
~Sub() {};
Sub* clone() const {return new Sub(*this);}
private:
double size;
Sub(const Sub &p) : Base(p.x), size(p.size) {}
protected:
virtual ostream& print(ostream &os) const {os << "SUB " << x << " " << size << endl;
return os; }
virtual void readStream( istream &is ) {
is >> x;
is >> size;
}

};

如果我注释掉析构函数、复制构造函数和赋值运算符,程序将构建并运行,并输出所需的结果。然而,valgrind 发现大量内存泄漏(很明显)。如果我包含这些函数,程序将以 Segmentation fault: 11 结束。我正在使用带有 os x 10.8 和 clang 编译器的 mac。我做错了什么?

最佳答案

您程序中的错误可能在复制构造函数中:

BasePtr::BasePtr( const BasePtr &baseptr ) {
if (baseptr.basevar != 0)
basevar = baseptr.basevar->clone();
else {
basevar = 0; // <<<< missing
}
}

如果不进行此更改,以下代码将产生错误:

BasePtr a; // a.basevar = 0
BasePtr b = a; // now b.basevar is not initialized
// destruction of b will call delete on an uninitialized pointer

关于c++ - 为类存储指向另一个类的指针复制构造函数析构函数和赋值运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23536285/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com