例如,我们有这个类:
class Coord
{
double x;
double y;
double z;
public:
Coord() { x = y = z = 0; }
void set(double xx, double yy, double zz)
{
x = xx;
y = yy;
z = zz;
}
void set_x(double xx) { x = xx; }
void set_y(double yy) { y = yy; }
void set_z(double zz) { z = zz; }
double get_x() { return x; }
double get_y() { return y; }
double get_z() { return z; }
};
在这7种方法中,我们可以设置并获得坐标的x,y和z。我感兴趣的是创建更少的方法set()
和get()
,我可以在其中调用类似的东西:
int main()
{
Coord c;
c.set_x(5); /* only set x */
c.set_y(6); /* or y */
c.set_z(7); /* or z */
c.set(1,2,5); /* or setting x, y and z */
c.get_x(); /* only get x */
c.get_y(); /* or y */
c.get_z(); /* or z */
}
答案 0 :(得分:6)
如果Coord
类很简单,那么它也可以是struct
。
无论如何,你可以这样写:
class Coord
{
public:
enum xyz {x = 0, y, z};
Coord() : vec{x, y, z} {}
template<xyz C> void set(double v) { vec[C] = v; }
template<xyz C> double get() const { return vec[C]; }
void set(double xx, double yy, double zz)
{
set<Coord::x>(xx);
set<Coord::y>(yy);
set<Coord::z>(zz);
}
private:
double vec[z + 1];
};
并以这种方式使用该类:
Coord c;
c.set<Coord::x>(5); /* only set x */
c.set<Coord::y>(6); /* or y */
c.set<Coord::z>(7); /* or z */
c.set(1,2,5); /* or setting x, y and z */
c.get<Coord::x>(); /* only get x */
c.get<Coord::y>(); /* or y */
c.get<Coord::z>(); /* or z */
答案 1 :(得分:1)
getter和setter旨在保护您的数据并提供封装。
例如,它们允许您为获取和设置操作添加副作用(例如写入日志),或者允许您在以后引发可怕问题之前尽早捕获无效值(例如,防止设置大于n的值) )。
这是一个简短而有人工作的二传器例子:
void set_x(int x)
{
// prevent an invalid value for x
if( x > 11 ) x = 11;
// set x
this.x = x;
// log the operation
log("user set x to {0}", x);
}
假设您的c.set.x(5)
示例未使用某些糟糕的预处理器宏,则需要Coord类具有名为set
的成员变量及方法
x()
y()
z()
这需要与在set_x()
类中编写set_y()
,set_z()
和Coord
方法一样多的代码,但这些方法不属于类Coord ,而是属于另一个本身用作Coord
成员变量的类。这样做实际上没有任何逻辑意义...... x,y和z值属于Coord,对它们的操作是Coord上的操作。
此外,方法x()
y()
和z()
将不再遵循制作方法动词的一般原则。任何用这些方法阅读课程的人都不知道z()应该做什么功能!
它还会造成重构的噩梦:例如,如果将来出现业务要求,这意味着没有Coords可以拥有大于21的x值,维持您的代码将不得不更改作为Coord成员的类而不是Coord类本身。
使用getter和setter方法进行封装通常是一个非常好的主意,在C ++中,内联的好处甚至可以不增加运行时开销。但要坚持“让一切尽可能简单但不简单”的原则。换句话说,get_x()和set_x()被广泛理解,有用,易于重构,方便,自我记录和高效......其他方法可能不那么容易。
答案 2 :(得分:0)
首先:您对c.set.x
的使用不起作用,因为您会在对象set
上调用公共元素c
,其中set
具有公共元素{{1 }}
我发现这两个课程都缺乏干净的代码标准和通常的getter和setter风格 - 即使没有指定任何语言。
通常的方法是创建以下内容:
x
虽然有些人更喜欢使用m_x作为setter变量参数或任何其他约定。
无论如何,每个人都会直接理解你的代码。能够设置和获取x,y,z的坐标值,如果有人关注,它会看起来很标准 - 默认行为:
class Coord
{
double x;
double y;
double z;
public:
Coord() {
x = 0;
y = 0;
z = 0;
}
Coord(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
void setX(double x) { this.x = x; }
void setY(double y) { this.y = y; }
void setZ(double z) { this.z = z; }
double getX() { return x; }
double getY() { return y; }
double getZ() { return z; }
};
答案 3 :(得分:0)
你已经得到了一些很好的答案,但如果你真的想要一个具有较少的setter和getter的语法,你也可以使用枚举。客户端语法可能会变得有点笨拙和笨拙,但它当然取决于您正在寻找的内容!
#include <iostream>
class Coord {
public:
enum Axis {
X = 0,
Y,
Z,
NUM_AXES
};
// Using extended initializer lists (C++11)
Coord() : axes_{0, 0, 0} {}
Coord(double x, double y, double z) : axes_{x, y, z} {}
void set(Axis a, double d) {
axes_[a] = d;
}
double get(Axis a) const {
return axes_[a];
}
private:
double axes_[NUM_AXES];
// Copy constructor and assgn. operator included for good measure
Coord(const Coord &);
void operator=(const Coord &);
};
int main()
{
Coord c(1, 2, 3);
std::cout << "X: " << c.get(Coord::X) << std::endl;
std::cout << "Y: " << c.get(Coord::Y) << std::endl;
std::cout << "Z: " << c.get(Coord::Z) << std::endl;
c.set(Coord::Y, 4);
std::cout << "Y: " << c.get(Coord::Y) << std::endl;
return 0;
}
答案 4 :(得分:0)
如果验证不是一个问题,那么公开它的或多或少的标准方法是从非const访问器返回可变引用,并从const one返回值。这允许您将接口与存储分开,而不会使语法过于繁重。
private:
double m_x, m_y, m_z;
public:
double & x() { return m_x; }
double & y() { return m_y; }
double & z() { return m_z; }
double x() const { return m_x; }
double y() const { return m_y; }
double z() const { return m_z; }
这将允许c.x()
获取x坐标的值,无论Coord
对象是否为const,并允许使用语法c.x() = value
设置值。
为了完整性,您可以使用以下代码获得所需的语法,但我强烈建议不要使用它。这是一个额外的代码,没有真正的好处,并创建一个不常见的语法,大多数程序员不会发现它直观。
该技术创建了两个嵌套类getters
和setters
,并将它们的实例公开为Coord
的公共成员。
这是作为如何实现您要求的结果的示例提供的,但我不建议采用这种方法。
class Coord
{
private:
double x, y, z;
public:
Coord();
Coord(double, double, double);
class setters {
friend class Coord;
private:
explicit setters(Coord &);
public:
setters(setters const &) = delete;
setters & operator=(setters const &) = delete;
void x(double) const;
void y(double) const;
void z(double) const;
private:
Coord & coord;
};
friend class setters;
class getters {
friend class Coord;
private:
explicit getters(Coord const &);
public:
getters(getters const &) = delete;
getters & operator=(getters const &) = delete;
double x() const;
double y() const;
double z() const;
private:
Coord const & coord;
};
friend class getters;
setters const set;
getters const get;
};
Coord::Coord() : x(0), y(0), z(0), set(*this), get(*this) { }
Coord::Coord(double px, double py, double pz) : x(px), y(py), z(pz), set(*this), get(*this) { }
Coord::setters::setters(Coord & c) : coord(c) { }
void Coord::setters::x(double px) const {
coord.x = px;
}
void Coord::setters::y(double py) const {
coord.y = py;
}
void Coord::setters::z(double pz) const {
coord.z = pz;
}
Coord::getters::getters(Coord const & c) : coord(c) { }
double Coord::getters::x() const {
return coord.x;
}
double Coord::getters::y() const {
return coord.y;
}
double Coord::getters::z() const {
return coord.z;
}
(Demo)
答案 5 :(得分:0)
这个奇怪的代码正是你所要求的 - 只是C ++的乐趣。不要这样做!
#include <iostream>
using namespace std;
class Coord {
double x;
double y;
double z;
public:
class Setter {
public:
Setter(Coord& coord) : c(coord) {}
void x(double value) { c.x = value; }
void y(double value) { c.y = value; }
void z(double value) { c.z = value; }
void operator()(double x, double y, double z) { c.x = x; c.y = y; c.z = z; }
private:
Coord& c;
};
class Getter {
public:
Getter(Coord& coord) : c(coord) {}
double x() { return c.x; }
double y() { return c.y; }
double z() { return c.z; }
private:
Coord& c;
};
Setter set;
Getter get;
Coord() : set(*this), get(*this) { x = y = z = 0; }
friend class Setter;
};
int main()
{
Coord c;
cout << c.get.x() << " " << c.get.y() << " " << c.get.z() << endl;
c.set.x(1);
c.set.y(2);
c.set.z(3);
cout << c.get.x() << " " << c.get.y() << " " << c.get.z() << endl;
c.set(5, 6, 7);
cout << c.get.x() << " " << c.get.y() << " " << c.get.z() << endl;
return 0;
}
输出:
0 0 0
1 2 3
5 6 7
答案 6 :(得分:0)
实际上可以根据您的要求减少功能,如下所示,
class Coord
{
double x;
double y;
double z;
public:
Coord() {
x = 0;
y = 0;
z = 0;
}
void GetValues(double* x=NULL, double* y=NULL, double* z=NULL);
void SetValues(double x=0, double y=0, double z=0)
/* You can use constructors like below to set value at the creation of object*/
Coord(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
/*You can set the values of x, y & z in a single function as follows. It can be used at any time without restriction */
void SetValues(double x, double y, double z)
{
if(x > 0) //It is optional to use condition so that you can update any one variable aloen by sending other two as ZERO
{
this.x = x;
}
if(y > 0)
{
this.y = y;
}
if(z > 0)
{
this.z = z;
}
}
/*You can Get the values of x, y & z in a single function as follows. Pass By Reference id the concept you need */
void GetValues(double* x, double* y, double* z)
{
if(x != NULL) //It x is not null.
{
x = this.x;
}
if(y != NULL)
{
y = this.y;
}
if(z != NULL)
{
z= this.z;
}
}
};
在打电话时你可以像下面这样打电话,
SetValues(10, 20, 0); //To set x and y values alone.
double x1 = 0;double y1 = 0;double z1 = 0;
GetValues(&x1, &y1, &z1)//It will return the values x1 y1 and z1 as 10, 20 & 0
答案 7 :(得分:-1)
你无法完全按照自己的意愿行事。
在
c.set.x(5); /* only set x */
c.set
子表达式正在从set
检索字段c
(除非set
是#define
- d宏,但这很愚蠢)。