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

时间:2015-06-18 15:06:41

标签: c++ gcc casting

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(),那么有何不同之处? 看起来它访问坏段但更奇怪的是,如果我进行内联投射My to In我无法访问In的正确值但它正确访问超类型Old {{1} } field(槽方法)。

gcc 4.7.2版(Debian 4.7.2-5)

1 个答案:

答案 0 :(得分:2)

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

要解决此问题,请在尝试打印之前初始化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;