需要一些帮助来理解类继承(C ++)

问题描述 投票:2回答:2

我正在尝试为我自己的目的扩展别人的API,并且我试图在这种情况下让我的头脑继承类继承。

我写过这个最小的程序:


    #include 

    class first_class {
    public:
        first_class() {};
    };

    class second_class : first_class {
    private:
        int y;

    public:
        int get_y() { return y; }
        second_class() {
            y=99;
        }
    };

    int main() {
        first_class* a = new first_class();
        second_class* b = new second_class();

        int q = ((second_class*)a)->get_y();
        printf("%d\n",q);

        int r = b->get_y();
        printf("%d\n",r);
    }

first_class什么都不做,并且没有成员。 second_class继承自first_class,但添加了私有成员y和getter函数get_y();

当我在second_class的实例上调用get_y()时,它按预期工作。当我在first_class的实例上调用get_y()时,我将其转换为second_class,它返回0。

这应该是什么?是否所有仅限子类的成员变量都自动设置为零,或者是编译器有时会做的那些通常发生但实际上没有保证的事情之一,它们实际上应该被视为未定义?

c++
2个回答
4
投票

当你施放指针时,它不会“转换”指向的对象(也不会以任何方式影响它)。这是一个noop,即在运行时没有任何事情发生。

相反,它只是改变了被指向对象的类型被认为是什么。这是一个编译时的概念。

因此,当你写:

(second_class*)a

你说:“我真的知道a指向的内存是一个second_class对象,我想这样访问它”。

但它不是,它是一个first_class。因此访问y数据成员没有意义。编译器最终会产生最终可能会读取您不应该读取的内存的代码。


现在,有一种方法可以通过基类调用成员函数,即通过实际对象的基类的指针或引用。您可以阅读它(子类型,多态和动态调度是您可能想要阅读的主题)。但在C ++中它需要:

  • 您正在通过基类访问(不是像您在这里所做的派生类);即向上倾斜与向下倾斜。
  • 类层次结构意味着以这种方式使用。通常,方法和析构函数将是整个层次结构中的virtual(在您的示例中没有)。

例如,请参阅:Why do we need virtual functions in C++?开始了解它。


2
投票

这应该是什么?

不,((second_class*)a)->get_y();调用未定义的行为

是否所有仅限子类的成员变量都自动设置为零,或者是编译器有时会执行的那些通常发生但实际上不保证的事情之一

也没有,你正在有效地读取不属于该对象的内存。任何事情都可能发生(因此未定义的行为)

© www.soinside.com 2019 - 2024. All rights reserved.