我学到了一点C#,现在我正在学习C ++。在C#中,数据隐藏可以通过get和set运算符完成,使得数据成员可以通过提供“get”而不是“set”来呈现为“只读”。
这将允许类(Person)包含另一个类(Account),使得Account类的公共函数可供Person.Account的用户使用,但是用户不能直接更改Account类,因为它是只读的。
这应该在下面的代码示例中更清楚。
我的问题是,既然C ++没有提供漂亮的get / set语法,那么下面的代码是否有C ++模拟?
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"
}
}
答案 0 :(得分:3)
这些特殊成员在C#术语中称为“属性”,并且在C ++中没有直接等同于它们。您既可以将该成员设为公用,也可以将其设为私有,并定义一个getter和setter方法,但是你不会有C#的语法糖,你必须明确地调用它们。
实际上,可以在C ++中对此行为进行编码,但这很难看,详见此处:http://www.cplusplus.com/forum/general/8147/
答案 1 :(得分:2)
这两种语言存在根本脱节。您说您希望帐户是只读的,但随后您在其上调用修改函数(Deposit
)。我的C ++有线大脑说这是gobbledygook。但当然,这是因为语言不同。分配意味着两种语言完全不同。在C ++中,它只是另一种修改操作。在C#中,它重新分配引用指向不同的对象。 (我想,但我实际上并没有使用C#,所以我可能错了)。
现在,我可能会离开这里,但我建议您在这个特定情况下实际上并不需要此功能。在我看来,它唯一的好处是保持Person.Account
引用的对象是唯一的。因此,两个Person
对象不共享相同的Account
对象。但这在C ++中是不必要的。变量是对象。它们不是共享的,除非您使用工具来显式地创建它们(使用引用,指针或智能指针)。所以,你真正想要的只是一个公共成员。
如果你真的只想禁止任务,那么你就可以做到。只需删除Account
的赋值运算符即可。或者,在C ++ 11之前,将其声明为private并且不提供实现。
如果我离开这里,您是否可以更加清楚自己想要实现的目标?因为,再说一次,用C ++表示你想要一个只读对象是没有任何意义的,但是你想修改它(你正在调用Deposit
)。我忽略了制作余额成员mutable
的可能性,但这似乎不适合这种情况。
答案 2 :(得分:1)
C ++似乎没有直接的等价物 - 它不是用类似属性的东西制作的,而C#是因为java已经实现了它。但是,和你一样,我想知道它是否完全可能并偶然发现this小宝石。基本上,它似乎是一个返回所需变量的方法 - 并将其设置为const,以便一旦拥有它就无法更改它,只有在使用该方法时才能有效地读取它访问它。因此,如果需要,可以使用类似的东西。实际上,如果你考虑它,“属性”或“getter和setter”实际上只是链接中的内容的实现 - setter有一个参数,它将局部变量设置为你想要的值,并且getter返回它的只读版本。
答案 3 :(得分:-1)
返回shared_ptr<Account>
。这样,消费者可以调用Account的方法,但不能覆盖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
}
这是有效的,因为返回共享指针会复制它,包括原始指针。对共享容器的更改仅影响副本,但取消引用底层指针会到达原始实例。