Then you only have to add another layer of encapsulation. Your current requirement is to use the encapsulated result during the encapsulation process. After all, it depends on which part of the code you don’t want to assign a value to that variable. First, distinguish which part is the user code, and then discuss the issue of access permissions.
If I have a member variable that is only assigned a value when a certain member function foo() is called, cannot I declare foo() as const?
If what you mean by "assignment" refers to initialization (assigning an initial value), it is impossible for the data members of a class not to be initialized. If this data member is not initialized in the constructor's initialization list, the compiler will perform default initialize. So it is not possible to initialize the data members of the class only within a certain member function.
If by "assignment" you don't mean initialization, but rather changing an existing value, you can do that by adding mutable to the data member declaration.
However, when using mutable, please note:
When changing the data member whose declaration contains mutable, it should not affect the external state of this class.
In other words:
Data members containing mutable in the declaration should be used to describe the internal state of the class. Changes to these data members will not logically change the state of the class.
For example, members used for program debugging, members used for caching (or delayed assignment), members used for access detection, members used for mutex locks, etc. can use mutable because of changes in these members It does not logically change the state of the corresponding class.
Give a few examples:
class C {
private:
mutable size_t visit_foo_count = 0; // 程序调试
public:
void foo() const {
// do something
++visit_foo_count;
}
};
int main() {
const C c;
c.foo();
}
In the above example, changing visit_foo_count does not logically change the state of class C. From the user's perspective, the effect is the same every time c.foo() is called.
The same is true for this example. From the user's perspective, the result is the same every time mo.pi() is called. The user does not know that the calculation of pi_val will only be performed on the first call, nor does he know if pi_val will not be calculated without calling it once.
Extension
C++11 Standard
C++11 Standard § 7.1.2/11 The mutable specifier on a class data member nullifies a const specifier applied to the containing class object and permits modification of the mutable class member even though the rest of the object is const.
A blog about mutable: C++'s mutable and conceptual constness
Stack Overflow discussion: Purpose of the mutable keyword
gcc can use the -fpermissive option to turn off this error, and then this error is a warning. If you are using another compiler, there must be corresponding options. I also think mutable is a good solution.
mutable, forgot?
Solution
Then you only have to add another layer of encapsulation. Your current requirement is to use the encapsulated result during the encapsulation process.
After all, it depends on which part of the code you don’t want to assign a value to that variable. First, distinguish which part is the user code, and then discuss the issue of access permissions.
If what you mean by "assignment" refers to initialization (assigning an initial value), it is impossible for the data members of a class not to be initialized. If this data member is not initialized in the constructor's initialization list, the compiler will perform default initialize. So it is not possible to initialize the data members of the class only within a certain member function.
If by "assignment" you don't mean initialization, but rather changing an existing value, you can do that by adding
mutable
to the data member declaration.However, when using
mutable
, please note:When changing the data member whose declaration contains
mutable
, it should not affect the external state of this class.In other words:
Data members containing
mutable
in the declaration should be used to describe the internal state of the class. Changes to these data members will not logically change the state of the class.For example, members used for program debugging, members used for caching (or delayed assignment), members used for access detection, members used for mutex locks, etc. can use
mutable
because of changes in these members It does not logically change the state of the corresponding class.Give a few examples:
In the above example, changing
visit_foo_count
does not logically change the state of classC
. From the user's perspective, the effect is the same every timec.foo()
is called.The same is true for this example. From the user's perspective, the result is the same every time
mo.pi()
is called. The user does not know that the calculation ofpi_val
will only be performed on the first call, nor does he know ifpi_val
will not be calculated without calling it once.Extension
C++11 Standard
A blog about
mutable
: C++'smutable
and conceptual constnessStack Overflow discussion: Purpose of the
mutable
keywordgcc can use the
-fpermissive
option to turn off this error, and then this error is a warning. If you are using another compiler, there must be corresponding options. I also thinkmutable
is a good solution.