主类中调用的类方法,更改不会在类方法外持久?

问题描述:

基本上,我有两个类,Peg和Disk。 (这是一个河内计划的塔)我有的文件是Disk.h,Disk.cpp,Peg.h,Peg.cpp和main.cpp。不知道这是否重要。这里是Disk.h的磁盘类主类中调用的类方法,更改不会在类方法外持久?

#include <vector> 
#include "gwindow.h" 
#ifndef DISK_H 
#define DISK_H 

class Disk 
{ 
private: 
    int xCoord; //x and y coords are for drawing in a gwindow 
    int yCoord; 
    int mHeight; 
    int mWidth; 
    COLOR mColor; 
    int mName; //helps me keep track of which is which 

public: 
    Disk(); //default constructor 
    Disk(int x, int y, int heightIn, int widthIn, COLOR colorIn); 
    void setXY(int x, int y); //this is the one I'm having trouble with 
    int getHeight(); 
    int getWidth(); 
    int getX(); 
    int getY(); 
    COLOR getColor(); 
    std::string diskColor(); 
    void draw(GWindow &gw); 
    void nameDisk(int name); //yet this one is working? 
    int getName(); 
}; 

#endif 

但是,我遇到了setXY函数的问题。当我从main调用它时,它会正确调用该函数,更改setXY范围内的变量,但该值不会保留在函数外部。然而,nameDisk工作正常,基本上是一样的,除了它正在改变mName而不是xCoord和yCoord。这里是setXY:

void Disk::setXY(int x, int y) 
{ 
    xCoord = x; 
    yCoord= y; 
} 

,这里是我如何把它从主:

pegVec[2].getDisks()[0].setXY(690, 200); 

我知道这看起来疯狂,但基本上pegVec是3个挂钩对象的载体。每个挂钩对象都有一个函数getDisks(),该函数返回当前挂钩上所有磁盘的矢量。因此,上面的行试图在第2个挂钩上执行setXY。对不起,如果这不清楚,但我已经尝试制作一个新的磁盘对象并在其上调用它,那也不起作用。

这里是getDisks,如果它的问题:

std::vector<Disk> Peg::getDisks() 
{ 
    return disksOn; 
} 

和disksOn只是钉的成员变量:

std::vector<Disk> disksOn; 

我认为这可能是与如何getDisks问题()的作品。我是一个noob,但我猜测,返回矢量disksOn使它的“副本”,这是我改变了我的setXY功能,但它不是相同的实际disksOn矢量相关Peg对象?我不知道这是否合理。

我试过到目前为止:

  • 制作XCOORD和YCOORD公共变量和更新它们手动,而不是使一个setter函数。这没有奏效。
  • 我在每一步打印出x和y值。在setXY中,值已成功更新,但是当函数结束时,他们又回到了原来的样子。
  • 我尝试了一些与const关键字混乱,但我不明白它,甚至无法让它运行。
  • 通过引用/值传递所有内容
  • 在接受Disk矢量作为输入并使用getDisks作为该函数的输入的main中创建一个新函数。没有工作,同样的问题。
  • 测试了我的另一个setter函数nameDisk,它工作正常。它基本上与setXY相同,这就是为什么我认为问题出在getDisks上。
  • 始终在各个点(heh)使用指针,但我不确定这是否是最佳方式。我昨晚搞砸了,所以我不记得100%,但我想我试图让getDisks返回一个指针,而不是矢量,我认为它没有问题,但它更可能是我的语法问题和我如何使用指针。我认为这可能有效,但我不知道如何动摇它。

帮助?

你是在正确的轨道上 - 不知何故,你正在看的不同于你自己认为的物体。使用引用是一个很好的解决方案,但你可能没有得到正确的;-)

尝试:

// Return reference to the disks on the peg. 
std::vector<Disk>& Peg::getDisks() 
{ 
    return disksOn; 
} 
+0

嗯,工作!非常感谢。我记得昨天晚上试了一下,但是我让事情变得更加复杂。 –

的问题是, std::vector<Disk> getDisks() { return disksOn; } 返回一个完全新的独立临时副本 disksOn而不是对原始的引用。所以你正在修改一个在声明结尾被丢弃的临时副本。

你需要为了返回参考到disksOn使用 std::vector<Disk> &getDisks() { return disksOn; }

虽然如果您要返回对矢量成员对象的引用,那么您可能会将对象直接作为公共对象访问,因为任何人都可以在此处操作矢量,并在服务时摆脱getDisks()函数在访问保护方面没有任何目的。

更好的设计是给访问单个磁盘:

Disk &getDisk(int index) { 
    return disksOn[index]; 
} 

const Disk &getDisk(int index) const { 
    return disksOn[index]; 
} 

背后不给人以矢量直接访问我们的想法是,如果需要在不改变外部的代码,你可以稍后更改基础容器类型Peg类。

第二个版本(const)对于访问const Peg对象的const Disks是必需的。

+0

感谢您的回答。你能解释一下const Disk对象和普通Disk对象之间的区别吗? const Disk对象是不可变的吗? –

+0

简单地说:是的。 A ** const **对象是一个不能直接更改的对象,只能调用它的const成员函数。然而,它可以通过对同一对象使用不同的非const指针或非const引用来改变,并且某些函数可能会通过执行必要的const_cast ()来改变它,例如,用于实现**引用计数对象**作为引用计数需要更新,即使该对象在概念上被认为是常量。所以要迂腐,它不是一成不变的。 –

+0

例如'int a = 5; const int&const_ref_a = a; cout