Reputation: 1711
This is kind of two questions in one :-D.
I am getting a couple a compilation errors when trying to use const.
What I am trying to achieve.
In my class constructor I pass a pointer to an object. I do not want the address and value of the object to change so I use const. Here is what my code looks like
Class Constructor
A::A( const B* const example ): m_example(example) {
m_mth1_ex = m_example->method1();
m_mth2_ex = m_example->method2();
}
In Class Header File
C* const m_mth1_ex;
D* const m_mth2_ex ;
Error that I am receiving:
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'
I thought since I am initializing these values in constructor this was alright, but I guess I declare them in the header file and const do not like that...
Secondly, the methods from class B do not return const objects does this matter?
Lastly, Since the methods come from class B which has a const value and address will can these methods change?
Upvotes: 0
Views: 2376
Reputation: 101496
const
members must be initialized in an initializer list, so this means you must do this:
A::A( const B* const example )
: m_example(example),
m_mth1_ex = m_example->method1(),
m_mth2_ex = m_example->method2()
{
}
However, now you've opened a huge can of worms with respect to order-of-initialization and maintainability. Members are initialized in the order of declaration, regardless of in what order you initialize them according to the code you've written. So, if m_meth1_ex
is declared before m_example
, m_meth1_ex
will be initialized first.
The above will work -- but you probably have a design flaw in your code. I would look in to coming up with a better design.
Upvotes: 0
Reputation:
You are not initializing those values, you are assigning to them and compiler complaints because you cannot assign values to constant (read-only) variables. You have to use constructor's initialization list in order to initialize class members. For example:
A::A (const B *const example)
: m_example (example)
, m_mth1_ex (m_example->method1 ())
, m_mth2_ex (m_example->method2 ())
{
}
Also, because order of declaration of the members matters, you have to be careful and watch out for the order of initialization. Basically, if you declare m_example
after m_mth1_ex
inside a class, this code will be undefined behavior, because m_mth1_ex
will get initialized first, even though it appears in the initialization list second.
In this particular example, it is safer to write this:
A::A (const B *const example)
: m_example (example)
, m_mth1_ex (example->method1 ())
, m_mth2_ex (example->method2 ())
{
}
Another important thing to remember about initialization list and constructors in general - if exception is thrown in constructor, destructor of that object is not called. So, if your method1 ()
and method2 ()
calls allocate memory, then this code is bad because once example->method2 ()
throws, you loose a pointer allocated by example->method1 ()
and have a memory leak. Unless m_mth1_ex
and m_mth2_ex
are some kind of smart pointers (i.e. std::unique_ptr
).
Upvotes: 2
Reputation: 477562
You are confusing initialization and assignment. The former is OK, the latter is not.
Use initialization properly:
A::A(const B* const example)
: m_example(example),
m_mth1_ex(m_example->method1()),
m_mth2_ex(m_example->method2())
{
}
(You might even prefer to use example->method1()
to decouple yourself from any particular declaration order of the member variables.)
Upvotes: 3