【问题标题】:C++: Casting my object to a different superclass results in a different pointer addressC++:将我的对象转换为不同的超类会导致不同的指针地址
【发布时间】:2011-01-17 22:53:55
【问题描述】:

我正在学习 C++,试图编写好的多态代码,但遇到了一些困惑。我有一个 Er_1Sine 类,它有两个超类:“Generator”和“Triggerable”。

Er_1Sine 如下所示:

class Er_1Sine : public Generator, public Triggerable{

}

如果我创建一个“生成器”指针 (gen),将其设置为“er1”,则指针地址与“er1”的地址匹配。但是,我的“可触发”指针“trig”的地址不匹配。这里发生了什么? trig 不是指向与 er1 和 gen 相同的对象吗?

er1 = new Er_1Sine();   
Generator *gen = er1;
Triggerable *trig = er1;

printf("\n\n er1 as Er_1Sine: %p \n", er1);
// outputs: "er1 as Er_1Sine: 0x4d28920"

printf("er1 as Generator address: %p \n", gen);
// outputs: "er1 as Generator address: 0x4d28920"   

printf("er1 as Triggerable address: %p \n\n", trig);
// outputs: er1 as Triggerable address: 0x4d289f8

【问题讨论】:

    标签: c++ inheritance pointers polymorphism


    【解决方案1】:

    这是多重继承 - 基类子对象与子实例的偏移量不同,因此地址不同。编译器前端必须在隐式向上转换期间调整指针值。

    【讨论】:

    • 我还要补充一点,出于这个原因,您可能不应该对指针值执行 == 来确定相等性。采用类似 Java 的方法并编写一个相等函数或运算符可能会更好。
    • 嗯,是的,也不是。比较指针是一种内置操作,您不能覆盖它。比较实例很可能需要一组自定义运算符。这里没有像 Java 那样的东西...... :)
    • 实际上使用 == 来表示指针相等对于确定它们是否指向同一个对象通常非常好,因为如果我正确阅读标准,指针只能在它们是相同类型时进行比较(在可能的类型转换之后),因此在这种情况下,当将基类指针与派生类进行比较时,后者将被隐式转换为基类(因此会进行相应调整),因此如果两者都来自相同的派生对象。
    • @Grizzly 过去,在调用与 == 和 != 进行比较的函数之前,我经历过不正确的转换导致的段错误(比较时没有发生崩溃,但在逻辑上紧随其后)。我觉得我说话很鲁莽。我经常做 ptr == 比较,但是如果它在我无法控制调用上下文的 API 函数中,我宁愿采取编写类成员来确定相等性的方法。此函数可以在派生类中隐藏,但不应是虚拟的。不过这也很麻烦,因为派生需要记住调用父相等函数。
    • @Grizzly 没有什么可说的,你不能比较对象部分的相等性,而不是宏观相等函数。显然,这取决于每个用例。
    【解决方案2】:

    虽然不是完全正确,但您可以将复合类视为堆叠在彼此顶部的 2 个单独的对象。您首先声明的那个是顶部(相同的地址),而声明的第二个是下面的(因此是不同的地址)。

    【讨论】:

      【解决方案3】:

      一个指针指向类的Generator 部分,另一个指针指向Triggerable 部分。它们不能是同一个指针,因为 Generator 和 Triggerable 是不同的。

      【讨论】:

        【解决方案4】:

        通过多重继承,不同的基类在子对象中可以有不同的内存地址。

        【讨论】:

          猜你喜欢
          • 2012-04-05
          • 1970-01-01
          • 2021-10-06
          • 2021-04-08
          • 1970-01-01
          • 2012-11-21
          • 1970-01-01
          • 1970-01-01
          • 2010-11-20
          相关资源
          最近更新 更多