Question

I have learned a bit of C# and now I am learning C++. In C# data hiding can be done with get and set operators in such a way that a data member can be presented as "read only" by providing a "get", but not a "set".

This would allow for a class (Person) to contain another class (Account) in such a way that the Account class's public function are available to the user of Person.Account, but the user cannot directly alter the Account class since it is read-only.

This should be more clear in the code sample below.

My question is, since C++ does not offer the nifty get/set syntax, is there a C++ analogue to the code below?

using System;

class Person
{
    private string _Name;
    public string Name { get { return _Name; } set { _Name = value; } }

    private Account _Account;
    public Account Account { get { return _Account; } }

    public Person()
    {
        _Name = "";
        _Account = new Account();
    }
}

class Account
{
    private decimal _Balance;
    public decimal Balance { get { return _Balance; } }

    public Account()
    {
        _Balance = 0;
    }
    public void Deposit(decimal deposit)
    {
        _Balance += deposit;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person();
        p.Name = "John Doe";

        // not allowed: p.Account = new Account();
        // Property or indexer 'CSharp.Person.Account' cannot be assigned to -- it is read only

        // allowed: the Account Object's public functions are available
        p.Account.Deposit(1000);

        Console.WriteLine(p.Account.Balance.ToString());
        // console says "1000"
    }
}
Was it helpful?

Solution 4

Return a shared_ptr<Account>. That way the consumer can call the Account's methods but can't overwrite Person._account.

#include <iostream>
#include <memory>

using std::cout;
using std::endl;
using std::shared_ptr;
using std::wstring;


class Account
{
  public:
    long Amount;
};

class Person
{
  private:
    shared_ptr<Account> _account = shared_ptr<Account>(new Account());

  public:
    wstring Name;
    shared_ptr<Account> GetAccount() { return _account; }
    shared_ptr<const Account> GetAccount() const { return _account; } // a const Person has a const Account
};

int main()
{
  Person p;

  shared_ptr<Account> a = p.GetAccount();
  a->Amount = 1;                          // access p.Account
  cout << a->Amount << endl;              // print 1

  Account* b = new Account();
  b->Amount = 2;

  a.reset(b);                             // doesn't affect p.Account

  cout << p.GetAccount()->Amount << endl; // still 1
}

This works because returning a shared pointer copies it, including the raw pointer. Changes to the shared container affect only the copy but dereferencing the underlying pointer reaches the original instance.

OTHER TIPS

These special members are called "properties" in C# terms, and there is no direct equivalent to them in C++. You can either make the member public, or make it private, and define a getter and setter method, but you won't have the syntactic sugar of C#, you'll have to call them explicitly.

Actually, it is possible to code this behavior in C++, but it's ugly, as detailed here: http://www.cplusplus.com/forum/general/8147/

There's a fundamental disconnect here in the two languages. You say you want the account to be read-only, but then you call a modifying function (Deposit) on it. My C++ wired brain says this is gobbledygook. But of course, this is because of a difference in the languages. Assignment means completely different things in the two languages. In C++, it is just another modifying operation. In C#, it is reassigning a reference to point to a different object. (I think, but I don't actually use C#, so I could be wrong).

Now, I may be way off here, but I would suggest that you don't actually need this feature for this particular case. It seems to me that the only benefit it has is keeping the object referred to by Person.Account unique. So two Person objects don't share the same Account object. But this is not necessary in C++. Variables are objects. They are not shared, unless you use facilities to explicitly make them so (using references, pointers or smart pointers). So, what you really want here, is just a public member.

If you really just want to disallow assignment, then you can do that. Just delete the assignment operator for Account. Or, prior to C++11, declare it private and provide no implementation.

If I'm off here, could you be more clear about what you are trying to accomplish with this? Because, again, it doesn't make any sense (in C++) to say you want a read-only object, and yet you want to modify it (which you are doing with the call to Deposit). I'm ignoring the possibility of making the balance member mutable, but that doesn't seem appropriate for this case.

C++ does not seem to have a direct equivalent - it wasn't made with something like properties in mind, while C# was because java was already implementing it. However, like you, I wanted to find out if it was at all possible and stumbled across this little gem. Basically, what it seems to be is that is a method that returns the variable that you want - and sets it to a const so that you can't change it once you have it, making it effectively read only when you use that method to access it. Hence, something like that could be used if need be. Actually, if you think about it, the "properties", or "getters and setters" are really just implementations of what is in the link - the setter has a parameter that sets the local variable to the value you want, and the getter returns a read only version of it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top