【问题标题】:C++ using const in object constructor and member functionsC++ 在对象构造函数和成员函数中使用 const
【发布时间】:2012-01-06 12:11:18
【问题描述】:

这是一个合二为一的问题:-D。

我在尝试使用 const 时遇到几个编译错误。

我正在努力实现的目标。

在我的类构造函数中,我传递了一个指向对象的指针。我不想改变对象的地址和值,所以我使用 const。这是我的代码的样子

类构造函数

A::A( const B* const example ): m_example(example) {

      m_mth1_ex = m_example->method1();
      m_mth2_ex = m_example->method2();

 }

在类头文件中

C* const m_mth1_ex;
D* const m_mth2_ex ;

我收到的错误:

error: uninitialized member 'A::m_mth1_ex' with 'const' type 'C* const'
error: uninitialized member 'A::m_mth2_ex' with 'const' type 'D* const'
error: assignment of read-only data-member 'A::m_mth1_ex'
error: assignment of read-only data-member 'A::m_mth1_ex'    

我认为既然我在构造函数中初始化这些值这没问题,但我想我在头文件中声明它们并且 const 不喜欢那样......

其次,B 类的方法不返回 const 对象,这有关系吗?

最后,由于方法来自具有 const 值和地址的类 B,这些方法可以改变吗?

【问题讨论】:

    标签: c++


    【解决方案1】:

    您混淆了初始化赋值。前者可以,后者不行。

    正确使用初始化:

    A::A(const B* const example)
    : m_example(example),
      m_mth1_ex(m_example->method1()),
      m_mth2_ex(m_example->method2())
    {
    }
    

    (您甚至可能更喜欢使用example->method1() 将自己与成员变量的任何特定声明顺序解耦。)

    【讨论】:

      【解决方案2】:

      您不是在初始化这些值,而是在为它们赋值并且编译器抱怨,因为您不能为常量(只读)变量赋值。您必须使用构造函数的初始化列表来初始化类成员。例如:

      A::A (const B *const example)
          : m_example (example)
          , m_mth1_ex (m_example->method1 ())
          , m_mth2_ex (m_example->method2 ())
      {
      }
      

      另外,由于成员的声明顺序很重要,您必须小心并注意初始化的顺序。基本上,如果您在一个类中在m_mth1_ex 之后声明m_example,则此代码将是未定义的行为,因为m_mth1_ex 将首先被初始化,即使它第二个出现在初始化列表中。

      在这个特定的例子中,这样写更安全:

      A::A (const B *const example)
          : m_example (example)
          , m_mth1_ex (example->method1 ())
          , m_mth2_ex (example->method2 ())
      {
      }
      

      关于初始化列表和构造函数的另一件重要的事情要记住 - 如果在构造函数中抛出异常,则不会调用该对象的析构函数。所以,如果你的method1 ()method2 () 调用分配了内存,那么这段代码就很糟糕,因为一旦example->method2 () 抛出,你就会丢失example->method1 () 分配的指针并发生内存泄漏。除非m_mth1_exm_mth2_ex 是某种智能指针(即std::unique_ptr)。

      【讨论】:

      • 我相信我会在构造函数中遇到这个问题。正如你所说,我需要重载 new 运算符,甚至更好地使用智能指针:-D
      【解决方案3】:

      const成员必须在初始化列表中进行初始化,因此这意味着您必须这样做:

      A::A( const B* const example )
      :  m_example(example),
         m_mth1_ex = m_example->method1(),
         m_mth2_ex = m_example->method2()
      {
      }
      

      但是,现在您已经在初始化顺序和可维护性方面打开了一大堆蠕虫。成员按照声明的顺序进行初始化,无论您根据您编写的代码以什么顺序初始化它们。因此,如果m_meth1_exm_example 之前声明,m_meth1_ex 将首先被初始化。

      上述方法可行——但您的代码中可能存在设计缺陷。我会考虑提出更好的设计。

      【讨论】:

        猜你喜欢
        • 2021-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-15
        • 2011-09-13
        • 1970-01-01
        相关资源
        最近更新 更多