草庐IT

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

coder 2024-02-19 原文

我是新来的,这是我的第一个问题。我对我的家庭作业有疑问。我被要求设计一个抽象类“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/

有关c++ - 为类存储指向另一个类的指针复制构造函数析构函数和赋值运算符的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  3. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  4. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  5. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  6. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  7. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  8. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

  9. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  10. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

随机推荐