user964843
user964843

Reputation:

making public member read only

class A{
    private:
        int a;
    public:
        const int &ref = a;
};

int main() {
    A obj;
    obj.a = 20;     // error cause private
    obj.ref = 30;   // not private but const so ERROR
    return 0;
}

I'm trying to make a member variable accessible but read only through the interface. Currently I've tried this approach and it seems to compile fine. I made a const reference to my original variable int a and made it public. Is there anything that's wrong with this practice that I might be missing out? Or is this example safe and sound to use for practical purposes?

Nothing wrong with providing a member function with const correctness applied (and I've used that too and intend to do so always), but I'm asking is there any thing wrong with this way if I have to provide a variable that is only read-only.

Thankyou :)

Upvotes: 0

Views: 2429

Answers (2)

James Adkison
James Adkison

Reputation: 9602

class A{
    private:
        int a;
    public:
        const int &ref = a;
};

is there any thing wrong with this way if I have to provide a variable that is only read-only

There are at least a couple drawbacks with this design decision for class A.

1: Class Size

Also as Dieter Lücking mentions in a comment:

increasing the size of the class, needlessly

2: Copy Semantics

It breaks the compiler generated copy assignment operator. For example, the following code behavior is generally desirable but doesn't work.

A obj1;

// ...

A obj2;

// make changes to 'obj2'

// Update 'obj1' with the changes from 'obj2'
obj1 = obj2; // This copy doesn't work!

More information:

There are certain rules when using references:

  1. A reference must be initialized when it is created. (Pointers can be initialized at any time.)
  2. Once a reference is initialized to an object, it cannot be changed to refer to another object. (Pointers can be pointed to another object at any time.)
  3. You cannot have NULL references. You must always be able to assume that a reference is connected to a legitimate piece of storage.

It may be possible to implement a custom assignment operator but that's more code to maintain (i.e., another drawback in my opinion).

#include <iostream>

class A
{
private:
    int a;

public:
    explicit A(int value) : a(value) {}

    A& operator=(const A& other)
    {
        a = other.a;
        return *this;
    }

    const int& ref = a;
};

int main()
{
    A obj1(10);
    std::cout << "1: " << obj1.ref << "\n";

    A obj2(20);
    std::cout << "2: " << obj2.ref << "\n";

    obj1 = obj2;
    std::cout << "1: " << obj1.ref << "\n";

    return 0;
}

The idiomatic way to address this issue is to use a proper accessor function.

class A {
    private:
        int a;

    public:
        int getA() const { return a; }
};

Upvotes: 3

Archimaredes
Archimaredes

Reputation: 1427

The standard way to do this in C++ is by making the actual member private but including a public 'getter' method for the interface, as below:

class A{
    private:
        int a;
    public:
        int get_a() const { return a; }

        A() : a(20) {}
};

int main() {
    A obj;
    int n = obj.get_a(); // n = 20
    return 0;
}

The user cannot set the value of A::a but can use A::get_a to retrieve its value.

Upvotes: 3

Related Questions