-3

I have the following structure of a class for read-only variables (principle taken from here)

#include <iostream>
#include "test.h"

using namespace std;

int main(int argc, const char * argv[]) {

    Test test;

    cout << test.x << endl; // Should be 0.
    test.f(test.x);
    cout << test.x << endl; // Should be 10.

return 0;
}

with the class Test

#ifndef __CPP_Playground__test__
#define __CPP_Playground__test__

#include <iostream>

class Test {
private:
    int x_;

public:
    const int &x;
    void f(int target);
    Test() : x(x_) {}
};

#endif /* defined(__CPP_Playground__test__) */

and the appropriate cpp file

#include "test.h"

void Test::f(int target){
    target = 10;
};

But it does not work. How can I fix this?

Community
  • 1
  • 1
DaPhil
  • 1,509
  • 4
  • 25
  • 47
  • 1
    You need to initialize `x_` in the constructor. And do something that actually has an effect in `Test::f()`. – juanchopanza Feb 09 '15 at 12:10
  • But that is my question: How can I change it so that it does have an effect? – DaPhil Feb 09 '15 at 12:13
  • Change the value of something that is not a local variable? Look at `Test::f()`. What is it doing? Nothing. – juanchopanza Feb 09 '15 at 12:14
  • And HOW can I change the value of x_ instead of the local variable but having the target variable? So that I could add an additional read-only variable int y_ with const int &y and also use function f to set it's value to 10? – DaPhil Feb 09 '15 at 12:17
  • `x_ = 10` would be one way of doing it. – juanchopanza Feb 09 '15 at 12:22

2 Answers2

1

If you really want to subvert const-correctness like this, then you'll have to pass by reference (so that you can modify the variable, not a local copy), and use an evil cast to get around the type system's protection against such craziness.

void Test::f(int const &target){
    const_cast<int&>(target) = 10;
};

This will have undefined behaviour if the reference is bound to a const object.

Usually, it would make more sense for member functions to access the private variables themselves; and it would be better to provide read-only access via a "getter" function rather than a reference, since that would take up no extra storage in the object.

(Also, you shouldn't use reserved names like __CPP_Playground__test__)

Community
  • 1
  • 1
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
0
void f(int target);

You're defining the parameter target to be passed by value, i.e. as a copy. Thus changing target inside f() will have no effect on the variable you passed to f().

To be able to modify an object passed to a function, the function needs to take that object as a reference. To declare f() to take a reference parameter:

void f(int& target);

Now you can modify the variable passed to f() inside the function and it will change also outside the function.


cout << test.x << endl; // Should be 0.

False. You haven't initialized x_ so the value of test.x can be anything. It is undefined.


test.f(test.x);

This will result in an error after defining f() to accept a reference variable, because test.x is const (i.e. it can't be modified) and f() needs a non-const reference.

Emil Laine
  • 41,598
  • 9
  • 101
  • 157