草庐IT

c++ - 自定义类/对象的构造函数和初始化

coder 2023-11-14 原文

我可以想象这个问题已经被问过了,但我实际上找不到任何合适的解决方案,所以如果这是一个多余的问题,请原谅。

我有一个自定义类

class myClass_A
{
public:
    myClass_A();          // Constructor
    myFunction_A();       // Some function from Class A
};

现在我有另一个自定义类,它有一个类型为 myClass_A 的成员

class myClass_B
{
public:
    myFunction_B();       // Some function from Class B

private:
    myClass_A m_instance; // Instance of Class A
}

现在 myFunction_B() 想从 m_instance 调用方法 myFunction_A() 有点像这样:

myClass_B::myFunction_B()
{
    m_instance.myFunction_A();
}

现在,如果我编译我的代码(这基本上就像我上面发布的示例),它将成功而不会出现任何警告或错误。所以我的问题是:

A.这个例子中会调用构造函数吗?

B.我真的可以从未初始化的对象调用方法吗?

C.假设未调用构造函数,但我仍然可以从该对象调用方法 -> 这是否仍然意味着我的类的成员未初始化?

如果这些问题有点愚蠢,我很抱歉,但我觉得我现在的理解速度很慢。

最佳答案

这些都是非常好的和重要的问题。

关于 A:

在执行构造函数的主体之前,C++ 会生成自动调用类的所有聚合(即成员)对象的默认构造函数 的代码。基本上,它所做的是转换以下代码:

class myClass_B {
public:
    myClass_B()
    {
        m_instance.foo();
        m_pInstance->foo();
    }
private:
    myClass_A m_instance;
    myClass_A* m_pInstance;
};

进入以下代码:

class myClass_B {
public:
    myClass_B()
        : m_instance()
        , m_pInstance()
    {
        m_instance.foo();
        m_pInstance->foo();
    }
private:
    myClass_A m_instance;
    myClass_A* m_pInstance;
};

编译器自动插入的两行称为initializer list ,它在执行构造函数的主体之前调用每个聚合对象的默认构造函数。请注意,第二个 m_pInstance() 调用了“指针的默认构造函数”,它创建了一个未初始化的指针;这几乎总是不是你想要的。请参阅下文了解如何解决该问题。

现在让我们假设 myClass_A 的构造函数具有签名 myClass_A(int someNumber),即它接受一个参数。然后,C++ 不能自动为 myClass_B 生成初始化列表,因为它不知道要将哪个数字传递给 myClass_A 的构造函数。它会向您抛出一个编译器错误,可能是提示缺少 myClass_A 的默认构造函数。您必须自己编写初始化列表,例如:

class myClass_B {
public:
    myClass_B()
        : m_instance(21)
        , m_pInstance(new myClass_A(21))
    {
        m_instance.foo();
        m_pInstance->foo();
    }
private:
    myClass_A m_instance;
    myClass_A* m_pInstance;
};

这是正确的代码,它调用 myClass_A 构造函数,参数 someNumber 的值为 21。这也显示了如何正确初始化指针:使其指向一些新分配的对象。

关于 B:

不像其他人说的那样,你可以! (试一试)

但它会导致意想不到的行为,这不是您想要的。 (包括只有当行星正确对齐时它才可能做你想做的事。)它很可能会崩溃但不保证会崩溃。这可能会让您度过漫长的调试之夜。如果您的编译器很聪明,它可能会识别出这一点并警告您,但它不会给您错误。

另请注意,对于具有默认构造函数的非指针聚合对象,默认构造函数 被调用,您将一切顺利。当您使用内置类型或指针时,问题就来了。这是使用未初始化的变量,是导致错误的最常见原因之一。如果您的代码做了一些非常奇怪的事情,请始终检查您是否初始化了所有变量。将任何成员变量的条目放入初始化列表中应该成为一种反射,即使它正在调用默认构造函数。把事情说清楚。

关于 C:

是的。详见 B。有趣的是,如果你调用的方法不使用“this”指针(这包括不使用任何属性变量和不调用任何使用属性变量的方法),你的方法保证工作。当您在未初始化的对象上调用方法时会发生什么,方法中的“this”对象(即所有属性变量也是如此)是随机内存。该方法的代码将执行但使用随机内存,这就是失败的原因。

我希望这能让事情变得更清楚一些。

关于c++ - 自定义类/对象的构造函数和初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9802341/

有关c++ - 自定义类/对象的构造函数和初始化的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  3. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  4. ruby-on-rails - 未初始化的常量 Psych::Syck (NameError) - 2

    在我的gem中,我需要yaml并且在我的本地计算机上运行良好。但是在将我的gem推送到ruby​​gems.org之后,当我尝试使用我的gem时,我收到一条错误消息=>"uninitializedconstantPsych::Syck(NameError)"谁能帮我解决这个问题?附言RubyVersion=>ruby1.9.2,GemVersion=>1.6.2,Bundlerversion=>1.0.15 最佳答案 经过几个小时的研究,我发现=>“YAML使用未维护的Syck库,而Psych使用现代的LibYAML”因此,为了解决

  5. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

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

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

  7. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  8. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  9. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  10. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

随机推荐