C++ getter 和 setter 最佳风格
Posted
技术标签:
【中文标题】C++ getter 和 setter 最佳风格【英文标题】:C++ getters and setters best style 【发布时间】:2011-04-26 09:08:19 【问题描述】:在 Java 中的代码约定简单明了,采用这种风格:
public:
int GetMyAge()
return myAge;
void SetMyAge(int myAge)
this->myAge = myAge;
private:
int myAge;
(我知道这是“又是同一件事”,但是)我已经阅读了关于 SO 的大部分相关问题,但我仍然不知道“最好的”和“最官方的”在 C++ 中做到这一点的方法。这不能只是偏好问题,可以吗?
编辑:
好像可以。
【问题讨论】:
***.com/q/1610029/11343的可能重复 @CharlesB,是的,这里的最佳答案与***.com/questions/760777/… 的答案相反,这就是为什么我不清楚使用女巫的原因 @CharlesB 也在处理一个常量,我们不在这里。虽然它确实带来了一个好点 - 这些都是简单的东西,可以是inline
d 虽然它们很小我无法想象任何值得它的盐的编译器不会为你内联它(考虑到 inline
修饰符无论如何只是一个建议。)
@dantuch 有几个不同答案的事实表明,glowcoder 是正确的:你的风格是最好的,C++ 中没有官方指南
编码风格是主观的,这个问题更适合程序员SE。
【参考方案1】:
最好不要这样做。你的年龄真的可以这样改变吗?盲目地为所有属性提供 getter 和 setter 表明你没有正确设计你的类。
【讨论】:
关于你的最后一句话,[citation needed]
如果我们总能处理不可变的类/对象,那就太好了。但我们不能,也不会。此外 - 有些事情确实发生了变化。考虑在游戏中改变位置的 Player 对象。
@glowcoder 大多数类在很多方面都是不可变的。考虑一个 BankAccount - 您可以更改帐号吗?不可以,但您可以更改帐户持有人的姓名。我的观点是,盲目地编写 getter 和 setter 是不好的做法。
@unapersson:这里的大多数人都会同意你的看法。但是,在某些情况下,您必须编写一个 getter,甚至有时,上帝保佑,一个 setter。
@glowcoder:getter/setter 的使用是简单而糟糕的设计。不幸的是,现实世界并不总能让我们做出完美的设计。注意:仅仅因为一个对象没有 getter 和 setter 并不意味着它是不可变的。玩家可以移动,因为它上面有 move()
方法,而不是通过 getter 和 setter 暴露 X/Y 坐标。当您引入现在必须维护的接口时,暴露类的内部会破坏封装(即使由 getter 完成)。方法应该(最好)通过作用于对象状态的动词。
我建议你不需要getPosition()
。问题是你为什么需要这个职位?把玩家画在棋盘上?然后你应该有一个 draw()
方法来传递板/屏幕对象。是不是因为要序列化?然后你应该有一个serialize()
方法,你也可以传递一个流。等 getter/setter 将对象的设计与使用该对象的代码紧密耦合。您想通过将操作对象的代码放入对象中来打破耦合。【参考方案2】:
最好的风格是让您和您的团队能够制作出您的客户继续为您付费的优质软件。
这种风格对您和您的团队有何帮助?您是否发现它会导致(或防止)错误?你觉得维护代码很容易吗?你对格式争吵吗?
回答这些问题,你的问题的答案就会从中产生。
【讨论】:
@Downvoter 关心评论如何改进这个答案? -1:这个答案对回答这个问题没有帮助,因为它太笼统了。制作糟糕的软件可能会在短期内完成任务,但如果他们必须维护由不遵循良好实践的过于笼统的风格产生的劣质代码,那么他们会很快让您和您的客户破产。 @Martin 任何进行尽职调查的软件公司都会分析他们的软件生产标准(命名约定、样式指南、构建例程、测试计划、部署程序等...)并确定导致问题(错误、增加的维护时间、性能瓶颈、内部战争等) - 事实是我们可以宣扬直到我们在超链接中出现蓝色,现实世界中没有最佳实践。这适用于个别公司以及这些公司内的团队。注意到您对使用 set/get 的宗教反对。 对于这些编码风格的问题,我最喜欢的部分是,最好的答案很少是倡导一种特定教义的答案。【参考方案3】:一个简单的答案:类名在 c++ 中通常是大写的(除了 std 类),方法是小写的,像 Qt 这样的一些框架更喜欢 camelCase,但我更喜欢 underscore_notation - STL 也是如此,例如。 “auto_ptr”。
类并不总是有单独的.h
文件,因为这里.java
文件被拆分为.h
标头(用于整个包)和.cpp
实现文件,每个类一个。
class TipicalCamelCase
public:
/// mark the frequently used small functions inline in the class def.
inline int getMyAge() const;
void setMyAge(int myAge=5); // defaults go to the definition.
/// for efficiently setting more complex things.
void setMyStuff(const MyStuff& myStuff);
/// a tipical class-valued getter
/// (sometimes scoffed at since it can have memory leaks
/// if you dismiss the class but still use and don't copy MyStuff.)
const MyStuff& getMyStuff() const;
/// a safe getter, but forces copying-out MyStuff.
MyStuff getMyStuff() const;
private:
int myAge;
static const int zero=0; // allowed only in the new C++11 standard.
static const int one;
;
一些实现/初始化(通常在单独的TipicalCamelCase.cpp
文件中):
const int TipicalCamelCase::one = 1;
int TipicalCamelCase::getMyAge() const
return myAge;
void TipicalCamelCase::setMyAge(int myAge_)
myAge = myAge_;
下划线样式相同,但
int Tipical_camel_case::get_my_age() const
return my_age;
我更喜欢这个,因为它在头文件和实现文件中看起来都更干净。
您可以看到函数标题比 java 中的要长。特别是你会看到templates
(泛型)2 行的标题是典型的,所以值得把它们分开一点。
template<typename _Tp>
int Class_name::general_function(_Tp);
我认为它应该作为风格介绍。
如果您使用继承,对于 java 风格的工作,标记除构造函数 virtual
之外的每个函数,以便 @overrides 行为正确。
【讨论】:
【参考方案4】:您在上面的代码中写的是正确的语法。如果您正在寻找一个经验法则,请以这样一种方式对您的访问器函数进行编码,以便它们被设置/获取准确的值。
EG:
void SetMyAge(int newAge)
if(newAge > 10 && newAge < 100)
_age = newAge ;
我更愿意将验证“newAge > 10 && newAge
void SetMyAge(int newAge)
if(IsValidAge() )
_age = newAge ;
但我想对此发表评论
void SetMyAge(int myAge)
this->myAge = myAge;
最好将类变量的命名约定与 _myAge 区分开来。
编辑 我认为变量名称理解不正确。
myAge 应该命名为 _myAge 。
【讨论】:
int int_myAge
?哦,拜托,来吧……
@glowcoder Hungarian notation 可以达到 nMyAge 。将 _ 附加到变量名是常见的做法,指的是类可见性。
@Sujay 附加,可能。前置,没有。
@Sujay 有多种形式的匈牙利符号。一种常见的方法是将_
或m_
附加到成员变量中。任何称职的 IDE 都会为您的变量进行颜色编码,并且它永远不会忘记这样做,就像命名约定一样。
我不喜欢你的第一个二传手。它会默默地失败,不让用户/程序员知道为什么没有设置属性。以上是关于C++ getter 和 setter 最佳风格的主要内容,如果未能解决你的问题,请参考以下文章
覆盖 ExtJS 模型 getter 和 setter 的最佳实践
用户定义类型的 getter 和 setter 上的 C++(类似 CAS)同步