C ++
更新指针的值或将指针更改为指向其他内容是否更好?
假设我们有两个类:球和坐标。
class ball
{
Coordinates *ballCurrent;
public:
ball(int);
~ball();
void setLoc(Coordinates&); // OR void setLoc(int, int);
};
class Coordinates
{
int x, y;
public:
Coordinates(int, int);
void setCoordinates(int, int);
};
对于ball类中的setLoc方法,哪个参数应该更好?通过使用(* ballCurrent).setCoordinates(int,int)或使用( ballCurrent).setLoc((new Coordinates(int,int)))来设置setLoc会更好吗?如果可能,请详细说明每个案例的原因。
答案 0 :(得分:3)
更新指针值或更改指针是否更好? 指向其他东西?
如果没有某些背景,这不是可以回答的问题。知道对象是不可变的通常很有用 - 只要你有一个指向该对象的指针,对象就不会在你的鼻子下发生变化。例如,如果函数或方法将指向不可变类型的指针作为参数,则您知道可以将对象传递给该函数,而不必担心该函数将更改该对象。
另一方面,可变对象也有它们的位置。首先,您有时希望能够在几个步骤中构建一个对象,而不是一次完成所有这些操作,并且您可能不希望在此过程中创建多个中间对象以获取最终对象。 / p>
所以,这取决于背景。我看到你提供了一个简单的例子,但我不认为即使你的例子也必须是正确的答案。这取决于对您来说重要的内容以及相关对象如何与系统的其他部分进行交互。我认为,我倾向于倾向于可变物体,因为在游戏中,几个物体可能需要了解球。如果移动球的唯一方法是创建一个新球并将其传递给所有关心它的其他物体,那么这很容易成为一个巨大的问题。然而,坐标对象很容易变成不可变的 - 任何需要知道球位置的人都应该向球询问它的位置。一旦他们得到它,他们可能希望该位置不会每隔几毫秒改变一次。如果你不使坐标对象不可变,那么处理这个问题的另一种方法是让球在有人问的时候复制它的位置,并分发该副本而不是返回指向它自己的位置对象的指针
答案 1 :(得分:1)
如果可以,我可以这样写:
class ball
{
Coordinates coordinate_; // better name than ballCurrent?
public:
explicit ball(int) // add explicit to avoid implicit converting
: coordinate_(0,0) // initialize corrdinate_ properly
{
}
~ball();
void setLoc(const Coordinates& co) // add const
{
coordinate_ = co;
}
void setLoc(int x, int y)
{
coordinate_.setCoordinates(x,y);
}
};
无需担心动态内存问题,可以通过函数重载以两种方式setLoc
。没有狂野的指针,没有后顾之忧。
答案 2 :(得分:1)
如果使用新对象,则需要为自己分配内存,并且还需要初始化(构造函数运行,分配属性等)。与仅更改已有对象的值(以及为此目的而创建的对象)相比,这是一个很大的开销。
此外,如果你创建一个新对象,你需要释放前一个指针的内存,这也是开销...所以只需更改你现有的对象。
答案 3 :(得分:0)
只需更改指向的对象的值即可。每次想要更新值时创建一个全新的对象都没有意义。
如果Coordinates具有const x和y值且没有setCoordinates函数,则可能必须创建一个全新对象而只是更改值的一种情况。但如果你需要经常更新坐标,那么这很可能是一个糟糕的设计决定。
而不是这个:
(*ballCurrent).setCoordinates(int, int);
你可以用这个:
ballCurrent->setCoordinate(int, int);
同样的事情,但更容易编写,很多人会发现它更具可读性。
答案 4 :(得分:0)
对于SetLoc(int,int)
,您在ball
构造函数上创建了Coordinates
和Coordinates
之间的依赖关系,更重要的是,它代表了什么。如果构造函数签名发生更改,则必须将这些更改传递到ball::SetLoc
。这个参数在一般情况下是有效的,你真的想避免传递一组参数来初始化一个对象组件。
在这种特殊情况下,Coordinates
体现了空间中的位置,并且可能应该带有一组操作它的方法,以便保持其实现细节不会遍及程序的其余部分。如果您希望移动到3D坐标系,理想情况下,您需要更改的是构造函数调用和类实现。所以你真的想把课外的必要变化减少到最低限度,这意味着要避免前面解释过的问题。
您提供了两种不同的解决方案来设置ball
对象的位置。实际上这些解决方案会出现吗?在一个简单的程序中,球位置硬编码,这是一种可能性,任何一种解决方案都可行。但是在更复杂的软件中,球位置可能最初由配置文件设置,并且在一些非平凡的计算之后完成位置的任何后续更新。在这种情况下,封装与类中坐标有关的所有逻辑更加可维护,并避免传递(int, int)
参数。
如果您担心内存分配开销(例如函数返回结果生成的临时值),可以通过明智地使用consts,引用甚至指针来缓解它们,并定义合理的复制构造函数。