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

标签 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 内联转换为 In,我将无法访问 In 的正确值,但它可以正确访问父类(super class)型 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 的一部分的拷贝. future 更改为 m不会影响 iv .当你写 iv.setValue(10) ,即更新 iv但不是 m .

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

关于C++ 内联转换和转换为变量的工作方式不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30919132/

相关文章:

c++ - QTableView,一个标题的多列

c++ - 使用 %s 调用 printf 并传递一个零长度的 char* 是未定义的行为吗?

c - 在构建时生成非字符串化文本文本宏

java - 无法使用autocmd设置的gcc在MacVim中编译java

C Guard 不能按预期与 rlutil.h 一起工作

c++ - 在 osx 上将已安装的卷识别为 CD/DVD

c++ - 一次窃取 std::array 而不是逐个元素

c - 我是否要转换 malloc 的结果?

java - 为什么我会收到此错误 "Type mismatch: cannot convert from Serializable to T"?

java - Eclipse - Java,从 double 转换为 int