【问题标题】:Base and derived classes C++基类和派生类 C++
【发布时间】:2017-03-20 16:17:09
【问题描述】:

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

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

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

【问题讨论】:

  • 解释为什么你认为你的代码会给出这些值。

标签: c++ class inheritance


【解决方案1】:

第一种情况:

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

第二种情况:

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


参考:Why a virtual call to a pure virtual function from a constructor is UB and a call to a non-pure virtual function is allowed by the Standard?

【讨论】:

  • 您的回复非常有帮助、清晰、完整。在继续课程之前,了解这一点对我来说非常重要。非常感谢。我现在明白了。
【解决方案2】:

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

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。通过输出,您应该能够重建执行顺序。

【讨论】:

    猜你喜欢
    • 2017-11-16
    • 1970-01-01
    • 2016-10-17
    • 2015-06-28
    • 2016-02-08
    • 2014-08-08
    • 1970-01-01
    • 1970-01-01
    • 2019-01-17
    相关资源
    最近更新 更多