C ++在对象构造函数和成员函数中使用const

时间:2011-11-25 16:48:53

标签: c++

这是两个问题:-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对象吗?

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

3 个答案:

答案 0 :(得分:3)

您难以理解初始化分配。前者是好的,后者不是。

正确使用初始化:

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

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

答案 1 :(得分:2)

您没有初始化这些值,您正在分配它们和编译器投诉,因为您无法将值分配给常量(只读)变量。您必须使用构造函数的初始化列表才能初始化类成员。例如:

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

另外,由于成员申报的顺序很重要,你必须小心并注意初始化的顺序。基本上,如果在类m_example之后声明m_mth1_ex,则此代码将是未定义的行为,因为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)。

答案 2 :(得分:0)

const成员必须在初始化列表中初始化,因此这意味着您必须执行此操作:

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

但是,现在您已经在初始化顺序和可维护性方面打开了大量的蠕虫病毒。成员按声明的顺序初始化,无论您根据您编写的代码按什么顺序初始化它们。因此,如果在m_meth1_ex之前声明m_example,则会首先初始化m_meth1_ex

上述方法可行 - 但您的代码可能存在设计缺陷。我期待着提出更好的设计。