基类和派生类C++

Base and derived classes C++

本文关键字:C++ 派生 基类      更新时间:2023-10-16

几天前,我想潜入C++世界。我正在研究基本类概念和派生类概念。有人可以解释以下两个代码片段的细微差别吗?

class A
{
    private:
    virtual int GetValue() { return 10; }
    public:
    int Calculate() { return GetValue()*1.5; }
};
class B: public A
{
    private:
    virtual int GetValue() { return 20; }
};
int main()
{
    B b;
    std::cout << b.Calculate() << std::endl;
    return 0;
}

输出为 30,但预计为 15

class A
{
    private:
    int m_data;
    public:
    A(): m_data(GetValue()) {}
    int Calculate() { return m_data*1.5; }
    virtual int GetValue() { return 10; }
};
class B: public A
{
    public:
    virtual int GetValue() { return 20; }
};
int main()
{
    B b; A* ap;
    ap=&b; 
    std::cout << ap->Calculate() << std::endl;
    return 0;
}

输出为 15,但预期为 30

有人可以解释并帮助我理解推理吗?我对这个概念的想法有问题,但我无法弄清楚。

第一种情况:

这是微不足道的。您有一个实例化的 B 实例,并且您计算return GetValue() * 1.5;它使用B::GetValue(),因为您已将GetValue()标记为在基类中virtual。因此,评估 20 * 1.5。

第二种情况:

没那么微不足道。在基成员初始化器中调用 GetValue() 来设置m_data的值。标准C++规定在这种情况下将调用基类GetValue()方法。(非正式地认为这是由于类B在类A完全构建之前不会构建(。因此,评估 10 * 1.5。有趣的是,如果GetValue()纯虚拟的,那么程序的行为将是未定义的


参考:为什么从构造函数对纯虚函数的虚拟调用是 UB,而标准允许调用非纯虚函数?

为第二个示例尝试以下代码:

class A
{
private:
int m_data;
public:
A(): m_data(GetValue()) { std::cout << "Init m_data and A ";}
int Calculate() { return m_data*1.5; }
virtual int GetValue() { std::cout << "GetValue from A ";return 10; }
};
class B: public A
{
public:
B() { std::cout << "Init B "; }
virtual int GetValue() { std::cout << "GetValue from B"; return 20; }
};
int main()
{
B b; A* ap;
ap=&b; 
std::cout << ap->Calculate() << std::endl;
return 0;
}

它与您已经拥有的相同,但具有输出。你应该得到GetValue from A Init m_data and A Init B 15.我希望现在你明白为什么你的输出是15.使用输出,您应该能够重建执行顺序。