【问题标题】:Value from default field initialization is not being assigned未分配默认字段初始化的值
【发布时间】:2019-10-04 06:46:10
【问题描述】:

我目前正在为我的操作系统类进行实验室工作,但我无法理解为什么我在类的默认字段初始化中指定的值没有被分配。我有以下调度程序类:

class LOOK : SSTF {
public:
    io_req* pop() override;
};

继承自这个调度器:

class SSTF : protected IOSched {
public:
    virtual io_req* pop() override;
    virtual void push(io_req* new_req) override;
protected:
    io_req* left_pop();
    io_req* right_pop();
    int dir;
    LinkedList left;
    LinkedList right;   
};

其中 IOSched 是一个纯虚类,带有 pop() 和 push() 方法以及一个 curr_req 字段,这就是 LinkedList 类:

class LinkedList {
public:
    io_req* pop();
    void push(io_req* new_req);
    void push_in_order(io_req* new_req);
    io_req* top() const;
    void reset_dist(io_req* new_curr);
private:
    void insert_between(io_req_node* new_prev, io_req_node* new_next, io_req_node* new_node);
    io_req_node* head = nullptr;
    io_req_node* tail = nullptr;
};

根据我对 C++ 的理解,当我这样分配一个新的 LOOK 对象时:

sched = (IOSched*)(new LOOK());

我将获得一个指向堆分配的LOOK 对象的指针,该对象将包含一个SSTF 对象,该对象将包含两个LinkedList 对象,leftright,它们将被初始化为@987654332 @ 和 tailnullptr

但是,由于某种原因,left.head 的值是 0x203d1,而其余的值是 0x0。这只发生在sched 被初始化为LOOK 对象而不是SSTF 时(对于实验室,我必须实现一些不同的算法)。

提前致谢!

【问题讨论】:

  • 您能否提供足够的代码让我们自己运行和测试它?我已尝试重现此问题,但无法重现。
  • 这是我用来尝试重现它的代码godbolt.org/z/A9a3hu
  • 这是一个实际编译的:godbolt.org/z/wXt_9m
  • 那个演员什么也没做。指针可以隐式转换为指向基类型的指针。如果你做对了,那就浪费了打字,如果你做错了,它可以隐藏错误(指针类型不兼容)。一般来说,你不想使用 c 风格的强制转换,无论如何 - 它们不提供类型安全。
  • 地狱的最深处是为那些制作爆炸到当前目录的tar文件的人保留的! - 是的,公共继承不受保护。然后当它告诉你你做错了什么时不要试图覆盖编译器。

标签: c++ oop inheritance constructor initialization


【解决方案1】:
sched = (IOSched*)(new LOOK());

您不能将指针投射到类之外的受保护基类:

class A{};

class B : protected A {
    void foo(){
        B b;
        A * a = &b; // this is ok
    }
};

int main() {
    A * a = new B; // this is not
}

改为使用公共继承 - 在传统的面向对象情况下,这几乎总是您想要的。

另外,不要在 c++ 中使用 c 风格的强制转换。如果你使用 static_cast,它会继续对你大喊大叫,因为你应该被骂:)

【讨论】:

    【解决方案2】:

    非静态成员初始化是 C++11 的扩展(参见 here)。

    由于你的成员不是静态的,你必须在构造函数初始化列表中初始化它们:

    class LinkedList {
    public:
        LinkedList() : head(nullptr), tail(nullptr) {}
        io_req* pop();
        void push(io_req* new_req);
        void push_in_order(io_req* new_req);
        io_req* top() const;
        void reset_dist(io_req* new_curr);
    private:
        void insert_between(io_req_node* new_prev, io_req_node* new_next, io_req_node* new_node);
        io_req_node* head ; // useless = nullptr;
        io_req_node* tail , // useless = nullptr;
    };
    

    或切换到 C++11 或更高版本。

    【讨论】:

    • 如果他至少没有使用 c++11,那就是编译器错误。 godbolt.org/z/0L38Fj 。如果他有编译器错误,他就不会得到任何值(对或错)。我们可以肯定地说这不是答案。
    • 是的,为此使用 c++11。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-24
    • 2014-12-29
    • 2022-12-21
    • 2020-02-08
    • 2021-01-19
    • 1970-01-01
    • 2020-08-16
    相关资源
    最近更新 更多