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
也比较副本。不管你怎么做,复印都是不必要的。对不起,如果我不清楚的话。事实上,区别在于我为什么首先问这个问题。我一直在寻找一种方法来获取对基类子对象的引用(这是一种很好的方式)——我能想到的唯一解决方案是复制子对象的方法。我不知道为什么会被否决。