C++ 返回对切片对象的引用(超类型)
考虑以下类别:C++ 返回对切片对象的引用(超类型),c++,inheritance,reference,object-slicing,C++,Inheritance,Reference,Object Slicing,考虑以下类别: class Coord { public: double _x, _y; Coord(double x, double y) { _x = x; _y = y; } }; class NamedPoint : public Coord { public: int _id; NamedPoint(int id, double x, double y) : Coord(x,y),
class Coord
{
public:
double _x, _y;
Coord(double x, double y)
{
_x = x;
_y = y;
}
};
class NamedPoint : public Coord
{
public:
int _id;
NamedPoint(int id, double x, double y) :
Coord(x,y),
_id(id)
{
}
};
我想创建NamedPoint的成员函数--coord()--它返回与NamedPoint对应的类型为coord的引用
例如,我想说:
const Coord& NamedPoint::coord()
{
return ((Coord)*this);
}
但是我得到一个关于临时变量的警告,我对此并不疯狂
当然,以下工作:
Coord coord()
{
Coord c = *this;
return c;
}
但我宁愿回信给你
有人知道使用继承类是否可以做到这一点吗
很抱歉没有解释函数的要点。对于Coord和NamedPoint,我以不同的方式重载==运算符。Coord只需检查{x,y},NamedPoint检查{id,x,y}。如果我在这个==测试之前忘记将NamedPoint强制转换为Coord,我将使用错误的版本
所以,当我意识到
(Coord)np1 == (Coord)np2
如果你能给我想要的,我宁愿用
np1.coord() == np2.coord()
我认为这更清楚地说明了发生了什么。函数的意义是什么
NamedPoint
可以隐式转换为Coord
:
void foo(Coord& c)
{
c._x = 5;
}
NamedCoord nc(0, 1, 2);
foo(nc); // c references the Coord part of nc
无论如何,您的函数只需使用以下转换:
const Coord& NamedPoint::coord()
{
// Bad: takes the value of *this and slices off
// the derived bits, leaving a temporary Coord.
/* return ((Coord)*this); */
// Good: takes the value of *this and refers
// to the base bits, no temporaries.
return *this;
// (Same as:)
/* return ((Coord&)*this); */
}
这个函数的意义是什么
NamedPoint
可以隐式转换为Coord
:
void foo(Coord& c)
{
c._x = 5;
}
NamedCoord nc(0, 1, 2);
foo(nc); // c references the Coord part of nc
无论如何,您的函数只需使用以下转换:
const Coord& NamedPoint::coord()
{
// Bad: takes the value of *this and slices off
// the derived bits, leaving a temporary Coord.
/* return ((Coord)*this); */
// Good: takes the value of *this and refers
// to the base bits, no temporaries.
return *this;
// (Same as:)
/* return ((Coord&)*this); */
}
@GMan给出了主要的解决方案 但是,更详细地注意这个问题可能会很有趣:
const Coord& NamedPoint::coord()
{
return ((Coord)*this);
}
这与:
const Coord& NamedPoint::coord()
{
Coord c = *this;
return c;
}
这里很明显,您返回的是对堆栈上一个临时文件的引用,这使得对它的引用毫无用处,因此出现了警告
现在在本例中,Coord
是基类,因此我们有@Gman给出的简单解决方案
在一般情况下,原则是如果你想引用
某物
,你最好确保某物仍然存在。@GMan给出了主要的解决方案
但是,更详细地注意这个问题可能会很有趣:
const Coord& NamedPoint::coord()
{
return ((Coord)*this);
}
这与:
const Coord& NamedPoint::coord()
{
Coord c = *this;
return c;
}
这里很明显,您返回的是对堆栈上一个临时文件的引用,这使得对它的引用毫无用处,因此出现了警告
现在在本例中,Coord
是基类,因此我们有@Gman给出的简单解决方案
在一般情况下,原则是,如果你想引用某个东西
,你最好确保某个东西
仍然存在。很抱歉没有明确这一点——这更像是一种“哲学”-键入thing——我相应地更新了我的问题。谢谢——我想我没有意识到转换为引用某种语法(Coord&)。谢谢。很抱歉我没有弄清楚这一点——它实际上更像是一种“哲学”类型的东西——我相应地更新了我的问题。谢谢——我想我没有意识到转换为引用某种语法(Coord&)。感谢。谢谢,我原以为这就是警告的意思。谢谢,我原以为这就是警告的意思。你似乎没有注意到/承认转换为Coord
,复制部分对象与转换为Coord&
,之间的区别,这将创建对点的基类子对象的引用。GMan的解决方案是后者,您编写的所有代码都是前者,这就是为什么您在第一个coord()
函数中收到警告。你说“我宁愿退回一份参考”,但你退回的是一份(部分)副本,而不是原件。然后(Coord)np1==(Coord)np2
也比较副本。不管你怎么做,复印都是不必要的。对不起,如果我不清楚的话。事实上,区别在于我为什么首先问这个问题。我一直在寻找一种方法来获取对基类子对象的引用(这是一种很好的方法)——我能想到的唯一解决方案是复制子对象的方法。我不知道为什么会被否决。你似乎没有注意到/承认转换为Coord
,,它复制对象的一部分,而不是转换为坐标&
,从而创建对点的基类子对象的引用。GMan的解决方案是后者,您编写的所有代码都是前者,这就是为什么您在第一个coord()
函数中收到警告。你说“我宁愿退回一份参考”,但你退回的是一份(部分)副本,而不是原件。然后(Coord)np1==(Coord)np2
也比较副本。不管你怎么做,复印都是不必要的。对不起,如果我不清楚的话。事实上,区别在于我为什么首先问这个问题。我一直在寻找一种方法来获取对基类子对象的引用(这是一种很好的方式)——我能想到的唯一解决方案是复制子对象的方法。我不知道为什么会被否决。