C++内联转换和转换为变量的工作方式不同

C++ inline casting and casting into variable works differently

本文关键字:转换 工作 方式不 变量 C++      更新时间:2023-10-16
class Old
{
    protected:
        long val;
    public:
        long myVal()
        {
            return val;
        }
        void myVal(long val)
        {
            this->val = val;
        }
};
template<typename T> class In: virtual public Old
{
    protected:
        T value;
    public:
        void setValue(T val)
        {
            value = val;
        }
        T getValue()
        {
            return value;
        }
};

class My: public In<int>, public In<bool>
{
};
int main(int argc, char **argv)
{
    My m;
    m.myVal(100);
    In<int> iv = (In<int>) m;
    std::cout << "start_ils: " << ((In<int>)m).getValue() << std::endl;
    std::cout << "start_vs: "<< iv.getValue() << std::endl;
    ((In<int>)m).setValue(10);
    std::cout << "=== old's val ===" << std::endl;
    std::cout << "old_vs: "<<iv.myVal() << std::endl;
    std::cout << "old_ilsi: " << ((In<int>)m).myVal() << std::endl;
    std::cout << "old_ilsb: " << ((In<bool>)m).myVal() << std::endl;
    std::cout << "=== set_ils ===" << std::endl;
    std::cout << "get_ils: " << ((In<int>)m).getValue() << std::endl;
    std::cout << "get_vs: "<< iv.getValue() << std::endl;
    iv.setValue(10);
    std::cout << "=== set_vs ===" << std::endl;
    std::cout << "get_ils: " << ((In<int>)m).getValue() << std::endl;
    std::cout << "get_vs: "<< iv.getValue() << std::endl;
}

此代码生成以下输出:

start_ils: -2126649320
start_vs: -2126649320
=== old's val ===
old_vs: 100
old_ilsi: 100
old_ilsb: 100
=== set_ils ===
get_ils: -2126649320
get_vs: -2126649320
=== set_vs ===
get_ils: -2126649320
get_vs: 10

如果我在内联或首次放入变量时将 My 转换为 In 以访问int getValue(),有什么不同的工作方式?看起来它是访问坏段,但更奇怪的是,如果我做内联投射我的 In 到 In,我无法访问 In 的正确值,但它正确访问超类型 Old 的 long val 字段(槽方法)。

gcc 版本 4.7.2

(Debian 4.7.2-5)

您的代码通过打印未初始化的变量导致未定义的行为。 其结果可能不稳定。

要解决此问题,请在尝试打印它们之前初始化valvalue。 (请注意,对于虚拟继承,只有派生最多的构造函数才能初始化变量)。

没有说你不理解程序输出的哪些部分。我猜你希望最后两个输出行显示相同的数字。

也许您不知道(In<int>)mm复制构造一个临时对象。

该行((In<int>)m).setValue(10);创建一个临时对象,将其值设置为 10 ,然后销毁该临时对象。它不影响m .

In<int> iv = (In<int>) m;行使iv成为m的一部分的副本。未来对m的更改不会影响iv。 当你写iv.setValue(10)时,它会更新iv但不会m

如果要通过基类引用m,请使用 static_cast<In<int> &>(m)&意味着形成引用,而不是按值复制。您可能还打算使用In<int> &iv = m;而不是In<int> iv = (In<int>) m;