我有一个矢量类
class Vector {
public:
double x, y, z;
Vector add(Vector v) {
return Vector(x+v.x, y+v.y, z+v.z);
}
};
我有一个Ray类
class Ray {
public:
Vector origin, direction;
Vector getOrigin() { return origin; }
};
在某些方法中,我这样做:
Vector x = ray.origin().add(normal); // doesn't work
Vector y = ray.getRayOrigin().add(normal); // works
错误消息:类型向量不提供调用操作符
为什么我不能直接访问矢量?
答案 0 :(得分:8)
因为origin
不是函数。访问它时删除括号。
答案 1 :(得分:2)
Xīcò有正确的解决方案,但不是正确的症状。
origin
不一定是一个功能。 Vector
类可以重载operator()
并被调用,就像它是一个函数一样,这就是编译器试图传递的消息。
ray.origin
允许任何人对ray
的{{1}}成员做任何事情,包括可能对origin
有害的事情。非常不酷。 setter和getter的目的是规范对成员变量的访问。目标是自卫。
OP的ray
方法不返回原点。它返回原始副本。恶意的cretin可以在不破坏getOrigin
的情况下对副本执行任何操作。这通常是正确的方式,除非要返回的对象被修改或复制成本过高。在该修改案例中,使用私有数据锁定返回的对象,并使用它自己的getter和setter。在昂贵的复制案例中,将返回值声明为ray
以减少损坏的可能性。
在允许进行更改之前,优秀的设置者将审核const
成员的所有输入。如果调用者尝试输入与origin
不一致的值,origin
可以将其降低。
通过ray
直接访问origin
可以.
无法进行任何辩护。它还可以防止ray
更改原始实现而不会破坏原始用户。
这些是否与ray
和Vector
这样的简单类有关,是编码风格和必要性的问题,但将数据访问锁定到最低限度是一个很好的习惯。在开发复杂的软件时必须深入了解。
答案 2 :(得分:1)
class Vector {
public:
double x, y, z;
Vector add(Vector v) {
return Vector(x+v.x, y+v.y, z+v.z);
}
};
class Ray {
public:
Vector origin, direction;
Vector getOrigin() { return origin; }
Vector& getOrigin2() { return origin; }
};
int main() {
Ray ray;
Vector v1 = ray.origin; // returns origin member
Vector v2 = ray.getOrigin(); // returns a copy of origin member
Vector v3 = ray.getOrigin2(); // same as v1, returns origin member
}