C++成员函数无法更改私有字段
C++ Member Function Cannot Change Private Field
OH!我发现了问题。正如我最后所说,这是一个简单的问题。在for循环中,我迭代了"粒子"的副本。我更新了它们,但操作不会影响存储在矢量中的原始值。
对于有关解决方案的请求,可以使用三种主要方式访问粒子对象。lvalue-ref
对象方式:
for (auto& p: particles)
...
或者通过迭代器:
for (auto it=particles.begin(); i<particles.end();++it)
...
或者通过简单索引:
for (size_t i=0; i<particles.size(); ++i)
...
对于那些对代码感兴趣的人,你可以看看下面:
如果我没有错过一些非常明显的东西,我会遇到一个非常奇怪的问题。
为了简化这个问题,我有一个名为"Particle"的类,它有一个叫做"update"的函数。粒子类有一些私有变量,如位置、速度等。更新函数应该进行一些计算,并为这些私有变量添加适当的值。但是,这根本不起作用。
事实上,我对变量的类型持怀疑态度,这是我写的一个类,"Vector2"。
为了给变量添加值,我使用了"+="运算符,我认为我在Vector2类中正确地实现了它们(?)。
为了澄清情况,IMHO,最好给出一些代码:
这是我的Vector2.h:
namespace sim {
#include <ostream>
#include <cmath>
using namespace std;
struct Vector2 {
double x, y;
Vector2& operator+=(const Vector2& rhs) {
this->x += rhs.x;
this->y += rhs.y;
cout << "op+=" << endl;
return *this;
}
Vector2& operator*=(double k) {
x *= k;
y *= k;
cout << "op*=" << endl;
return *this;
}
friend ostream& operator<<(ostream& os, const Vector2& v2);
friend Vector2 operator+(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator-(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator*(Vector2 lhs, double k);
friend Vector2 operator*(double k, Vector2 rhs);
};
ostream& operator<<(ostream& os, const Vector2& v2) {
os << "[ " << v2.x << "; " << v2.y << " ]";
return os;
}
Vector2 operator+(Vector2 lhs, const Vector2& rhs) {
lhs += rhs;
cout << "op+" << endl;
return lhs;
}
Vector2 operator*(Vector2 lhs, double k) {
lhs *= k;
cout << "op*" << endl;
return lhs;
}
(删除了一些不相关的部分,如构造函数)
这是粒子类:
class Particle {
private:
Vector2 pos;
Vector2 vel;
Vector2 acc;
double rad;
SDL_Color clr;
public:
Particle(
Vector2 _p,
Vector2 _v,
Vector2 _a,
double _r = 10.0,
SDL_Color _c = { 255, 255, 255, 255 }) {
pos = _p;
vel = _v;
acc = _a;
rad = _r;
clr = _c;
}
Vector2& move_particle(Vector2 move_by) {
return (pos += move_by);
}
void update(double dt) {
this->vel += acc * dt;
this->pos += vel * dt;
cout << "update " << pos << vel << acc << endl;
}
void render(SDL_Renderer* renderer) {
// TODO: this was supposed to be a circle, but, who cares? ;)
SDL_Rect r = { int(pos.x), int(pos.y), int(rad), int(rad) };
SDL_RenderFillRect(renderer, &r);
cout << "render" << endl;
}
};
结果是:更新不会更新。
我怎么知道(猜测)我的过载是否有效
对于3个Vector2
对象,我可以执行我正确定义的任何类型的操作。结果正是他们所期望的。(或者,也许不是?)
但调试更新函数大致让我明白,实际上+=运算符只工作一次,不会再工作了,但这种行为只在更新函数中表现出来。
我知道,这将是一个如此简单的错误,我可能会感到羞愧(只是开玩笑)。
哦,当然还有主要代码:
int main() {
SDL_Init(SDL_INIT_EVERYTHING);
auto window = SDL_CreateWindow("My Very First Particle Simulation", -1, -1,
1024, 768, SDL_WINDOW_SHOWN);
auto renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
const Vector2 g(0.0, 9.8);
double dt = 0.1;
std::vector<Particle> particles;
bool quit = false;
while (!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
quit = true;
break;
case SDL_MOUSEBUTTONUP:
particles.emplace_back(Vector2(event.button.x, event.button.y), Vector2(1.0, 0.0), g);
break;
default:
break;
}
SDL_RenderClear(renderer);
for (auto p : particles) {
p.update(dt);
p.render(renderer);
}
SDL_RenderPresent(renderer);
}
}
}
对代码的一些评论,你可以将这些更改为会员功能
friend Vector2 operator+(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator-(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator*(Vector2 lhs, double k);
friend Vector2 operator*(double k, Vector2 lhs);
如
Vector2 operator+(const Vector2& rhs);
Vector2 operator-(const Vector2& rhs);
Vector2 operator*(const double k);
friend Vector2 operator*(const double k, Vector2 lhs);
在它们中,将this
复制到新的Vector2
,然后更新值并返回。第四个函数是作为朋友保存的,这样你就可以拥有类似double*Vector2的东西,而第三个函数则负责Vector2*double
任何将Vector2作为左操作数的操作都可以作为成员函数执行。
我可以看到这两个运算符正在按值获取它们的第一个args。更改它们,以便通过引用获取它们的参数。
Vector2 operator+(Vector2 lhs, const Vector2& rhs) { // lhs should be a const reference
lhs += rhs;
cout << "op+" << endl;
return lhs;
}
Vector2 operator*(Vector2 lhs, double k) { // lhs should be a const reference
lhs *= k;
cout << "op*" << endl;
return lhs;
}
编辑:
此外,这些函数应该将其类参数作为const
引用:
friend Vector2 operator+(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator-(Vector2 lhs, const Vector2& rhs);
friend Vector2 operator*(Vector2 lhs, double k);
friend Vector2 operator*(double k, Vector2 rhs);
- C++:用户定义的类,以成员字段作为地址
- 用于基于成员字段或函数创建比较器的快捷方式
- 无法初始化以 std::byte 作为成员类型的位字段
- 与位字段的并集为位字段成员提供了意外值
- 依赖注入:依赖关系需求字段/成员
- uninit_member:非静态类成员字段 m_cJobState.bstatus 未在此构造函数中初始化,也不在其调
- 派生类中的成员字段别名(无访问器功能)
- 使用静态类成员而不是私有字段之间的速度差异是什么?
- 如何使用 Clang 查找所有成员字段读/写?
- 位字段成员的类型
- 无法汇总初始化类型结构的变量,其中包含在类模板中的位字段成员
- C 模板功能在任何集合成员字段上迭代
- 一次启用 MANY 类的成员字段,具体取决于模板<T>
- 导致IAR ARM中出现错误的成员结构位字段元素的Initializer列表初始化
- 如何在C++的专用模板类中访问模板类成员字段
- 动态链接到 c++ 静态成员字段时符号查找失败
- std :: async在成员字段的成员功能上
- C :初始化成员结构的静态字段的正确方法
- 位字段成员的大小
- 如何为具有位字段成员的类专门化“swap”