【问题标题】:constructor with virtual function call in c++在 C++ 中具有虚函数调用的构造函数
【发布时间】:2010-12-31 23:42:34
【问题描述】:

首先,下面的代码不能用 Visual c++ 工作,而是用流血工作

输出为 0 ,但 acc.对我来说应该是 1 ;谁能解释一下这个

#include<iostream>
using namespace std;
class shape
{
public:
    virtual void print() const =0;
    virtual double area() { return 0.0;}
};
class point : public shape
{
    int x;
    int y;
public :
    point(int a=11, int b=11)
    {
        x=a;
        shape *s;
        s=this;
        cout<<s->area();
        y=b;
    }
    double area()const {return 1.0;}
    void print() const
    {
        cout<<"\nPoint\n";
        cout<<x<<"\t"<<y;
    }
};

int main()
{   
    point p(1,2);
    return 0;
}

【问题讨论】:

  • 重复,参见 e。 G。 stackoverflow.com/questions/962132/…
  • 我投票支持重新开放。这不是完全重复的。这个问题与 const/nonconst 覆盖有问题,并且调用没有发生在基类的构造函数中(与链接的“重复”相反)。声称任何构造函数问题的答案是完全错误的。如果您在 main 中执行 cout &lt;&lt; ((shape*)&amp;p)-&gt;area();,则会出现同样的问题

标签: c++ constructor virtual


【解决方案1】:

在函数的构造函数中调用虚函数就像该函数不是虚函数一样。这可能会令人困惑,但这是 c++ 中的标准行为

如果你想实现你的目标,那么你可能应该有一个“初始化”函数,你在构造函数之后调用它,其中虚函数调用将按照你的预期工作。

【讨论】:

  • 其实,这并不令人困惑。如果函数以虚拟方式运行并调用派生类方法,那么我们将在派生类构造函数没有先执行的情况下调用该方法。
  • 实际上,在构造过程中调用虚方法是未定义的行为。 Tarydon 提出的理性是不这样做的最佳逻辑理由。从编译器的角度来看,它取决于编译器如何实现虚拟方法(并且是故意的),标准未定义以使编译器尽可能高效。因此,不同的编译器以不同的方式执行(如 OP 结果所示)。
  • @Martin,C++ 标准 12.7p3:“可以在构造或销毁 (12.6.2) 期间调用成员函数,包括虚函数 (10.3)。”
【解决方案2】:

你得到了正确的输出。应该是0。当您在派生类的构造函数中调用area() 时,实际上调用的是area() 的基本版本而不是派生版本。在构造函数中调用虚函数不会调用派生类中的覆盖函数。

阅读this.

【讨论】:

  • 这个答案是错误的。请注意,FAQ 说“当我的基类的构造函数在其 this 对象上调用虚函数时”——但在代码中调用是由派生类的构造函数完成的。
  • 我发布链接只是为了展示给定机制的工作原理(在构造函数中调用函数)。
  • 如果派生类中的调用真的会覆盖基类函数,它应该命中派生类函数。但这不是因为const。它与构造函数无关。
  • 这个答案是错误的。请修复。在构造函数/析构函数中对虚函数的任何调用都有未定义的行为(如调用者所证明的,根据编译器有两个不同的答案)。这完全取决于编译器如何实现虚拟调用机制。像往常一样,C++ FAQ 精简版掩盖了细节(不是一个好的参考来源)。
  • @Martin,C++ Standard 12.7p3(我强调):“成员函数,包括虚函数(10.3),可以在构造或销毁期间调用(12.6.2 ). 当从构造函数(包括从数据成员的 mem-initializer)或从析构函数直接或间接调用虚函数,并且调用所应用的对象是正在构造或销毁的对象时,调用的函数是在构造函数或析构函数自己的类或其基类之一中定义的。"
【解决方案3】:

从构造函数调用虚函数是一个非常糟糕的主意。有关详细信息,请参阅此Calling virtual functions from constructor(请参阅第 3 段)。

【讨论】:

  • 请使用比 C++ FAQ lite 更权威的东西(如 C++ 标准)。它(C++ FAQ Lite)已知有很多错误和误导性信息(尽管它确实有一些有用的信息)。
  • Effective C++ 同意 Naveen :)
【解决方案4】:

您的代码中有一个细微的缺陷:

double area()const {return 1.0;}

基类的area() 方法未声明const。 point::area 因此不是虚拟方法。要么声明 shape::area const 要么从 point::area 中删除 const ,它将按预期工作。

【讨论】:

  • 这看起来是个问题。因为指针不是“const shape *”,所以它不会调用 const 函数,而是调用非 const 函数。您必须确保声明相同
  • @mayur,如果对您有帮助,您不妨接受他的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-05
  • 2012-01-28
  • 2013-02-18
  • 2015-03-17
  • 1970-01-01
相关资源
最近更新 更多