[英]Using getters and setters with user input in c++
如果这低于社区的工资等级,请提前道歉。 我刚开始学习面向对象编程,英语不是我的母语。
我刚刚了解了使用 getter 和 setter,以及数据封装的重要性。 但是,我在网上看到的所有使用 getter 和 setter 的示例都处理静态值,如下所示:
#include <iostream>
using namespace std;
class Employee {
private:
// Private attribute
int salary;
public:
// Setter
void setSalary(int s) {
salary = s;
}
// Getter
int getSalary() {
return salary;
}
};
int main() {
Employee myObj;
myObj.setSalary(50000);
cout << myObj.getSalary();
return 0;
}
我设法通过声明另一组变量并将它们作为参数提供给如下设置器来允许用户输入:
int main() {
Employee myObj;
int salary;
cout<<"Enter salary: " << endl;
cin>>salary;
myObj.setSalary(salary);
cout << myObj.getSalary();
return 0;
}
这是允许用户输入的唯一方法吗? 除了声明另一组局部变量之外,有没有更优雅的方法来完成这个?
对不起,如果这是一个初学者问题。 我是 C++ 游戏的新手,但我的脚还是湿了。
这是允许用户输入的唯一方法吗? 除了声明另一组局部变量之外,有没有更优雅的方法来完成这个?
(来自评论)
我希望我可以对 myObj.setSalary(cin) 做一些变化,这样 cin 就可以将值直接输入到 getter 中,而不必将它传递给临时变量
我不会将来自stdin
与 setter 混合,最好将它们作为单独的方法保留:
class foo {
int x;
int other_member;
public:
void set_x(int a) { x = a; }
void set_other_member(int a) { other_member = a; }
void read_x(std::istream& in) {
in >> x;
}
};
这让你写
f.read_x(std::cin);
从stdin
读取x
。
请注意,有很多方法可以实现相同的目标,而“优雅”则是相当主观的。 通常,您会为operator>>
提供重载以从流中读取foo
:
std::istream& operator>>(std::istream& in, foo& f) {
int a,b;
in >> a >> b;
f.set_x(a);
f.set_other_member(b);
}
要么这样做(使用 setter),要么让操作符成为foo
的朋友(直接访问foo::read_x
),或者使用foo::read_x
来实现它。 然后你可以写
foo f;
std::cin >> f;
请注意,C++ 不是“纯粹的”OOP 语言,惯用的 C++ 会很乐意避开某些 OOP 原则,而在适用的情况下支持更简单、更有效的代码。
如果您希望数据类型仅“保存”数据,则使用普通的旧struct
(带有公共数据字段)是完全可以接受的。 不要将封装的好处(...非平凡的构造,因此您可以在内部更改它们的实现)与任何类型的“安全性”混淆。 无论是否使用 Getter/Setter,任何人都可以更改您对象的数据。 顺便说一句,这使得读取数据更容易。
cin >> e.salary;
如果您不想要“只是一个结构体”,那么拥有一个设置有意义的初始值的构造函数是一种很好的风格,这样您就不会有“未初始化的” Employee
对象四处乱飞( RAII )。 这意味着您的客户端和析构函数都不必处理Employee
可能实际上不是一个(持有空指针或其他类型的未初始化资源)的可能性。
Employee e( "Mark Smith", 10000 );
一旦你到了那个时候, Employee
应该对Employee
对象发生的任何事情负责。 这意味着它不应该是其他人在读取用户输入并将其写入Employee
数据字段(通过 setter 或不通过),它应该是发送到Employee
对象的消息,它应该从输入或其他方式更新其字段,如合适的。
(考虑一下有人将您的指针成员设置为nullptr
的可能性,或者更糟的是,一些随机值。您的析构函数会尝试释放资源,然后您将如何调试该无效指针的来源?)
此时我们到达operator>>()
,它可以为 istreams 和您的类重载。
class Employee
{
public:
// ...
friend istream & operator>>( istream &, Employee & );
// ...
};
istream & operator>>( istream & in, Employee & e )
{
getline( e.name, in );
in >> e.salary;
return in;
}
int main()
{
Employee e; // For the sake of example, a default constructed employee
cout << "Enter new employee's name (on its own line), and salary:\n";
cin >> e;
}
一旦到达那里,您就会了解数据封装的实际含义: Employee
是一个对象,而不是数据容器。 你不应该在它的内部闲逛,你应该发送消息。
Employee e( "Mark Smith", Role::INTERNEE, 10000 );
cout << e; // Output: "Mark Smith, Internee, with an income of 10.000 sicles."
e.promote( Role::TEAM_LEAD, 10000 ); // Exception: "Wrong pay scale for Team Leads."
e.promote( Role::TEAM_LEAD, 30000 );
cout << e; // Output: "Mark Smith, Team Lead, with an income of 30.000 sicles and a free car."
请注意Employee
类是如何检查新工资的,并且知道晋升为 Team Lead 会自动包含一辆免费汽车,并且无需您自己设置即可做到这一点。 这就是这个封装的意义......
至于你的问题“as ask”,你的实现是否可以更优雅地读取薪水,你当然可以......
void setSalary(istream & in) {
in >> salary;
}
...和...
cout << "Enter salary:" << endl;
e.setSalary( cin );
并且因为它被正确封装,你可以添加健全性检查,将salary
类型更改为BigNum
,或者开始支持阅读BigNum
。
这个问题是一个一般性的答案将涵盖你的问题
所以在 OOP 中,只制作和使用副本或OBJECT
是一个核心概念,你制作一个类的单个副本OBJECT
的方式是标准的,但是你有没有想过MAKING AN ARRAY OF TYPE "YOUR CLASS's Objects"?
因为在您的情况下, obj
只会保存Employee 的一个副本,但是如果您使用数据结构(例如“数组”)来存储多个对象,那么它会更容易让我为您澄清
例子
int a, b, c, d, e, f, g ... z;
为所有这些字母分配一个值将是一个巨大的痛苦,但等待您可以拥有一个数据结构。
int arrayOfAlphabets[26];
现在要赋值? (您可以动态分配它,但这只是一个示例,向您展示您只需使用计数器即可控制变量的分配)
for(int x = 0 ; x < 26; x++){
arryOfAlphabets[x] = someNumber
}
想要获取值? 您可以动态获取值,但这只是一个示例,向您展示您只需使用计数器即可控制变量的设置和获取)
for(int x = 0; x < 26; x++){
cout << "Value of Alphabet" + x + " is: " + arrayOfAlphabets[x] << endl;
}
现在您已经看到了使数据结构特定的数据类型可以消除您的很多痛苦的示例,现在为了理解起见,请记住,
你的类是你创建的数据类型
class Employee {
private:
// Private attribute
int salary;
public:
// Setter
void setSalary(int s) {
salary = s;
}
// Getter
int getSalary() {
return salary;
}
};
主要你能做的是
int main(){
Employee emp[5];
int tempSalery;
for( int i=0; i<5; i++ )
{
cin >> tempSalery;
emp[i].setSalery(tempSalery);
}
}
现在打印你的结果
for( int i=0; i<5; i++ ){
cout << "Employee " + x + "Salery is: " + emp[i].getSalery() << endl;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.