覆盖函数及其在基类中的调用

时间:2014-08-16 19:15:00

标签: c++ class override

假设我有这两个类:

class A {
public:
    A() { foo() };
protected:
    virtual void foo();
};

class B : public A {
public:
    B() : super();
private:
    typedef A super;
    void foo();
};

如果我创建一个对象B,有没有办法强制A的构造函数在调用它时使用overriden方法?

4 个答案:

答案 0 :(得分:2)

没有。事实并非如此。 根据Effective c ++,当对象初始化时,虚函数不起作用。 (我用手机写的所以这里可能是错别字)

最好的问候。

答案 1 :(得分:1)

C ++标准,第12.7节[构造和销毁]:

  

可以调用成员函数,包括虚函数(10.3)   在建造或毁坏期间(12.6.2)。当虚拟功能是   直接或间接地从构造函数或析构函数调用,   包括在建造或破坏班级期间   非静态数据成员以及调用适用的对象   正在构建或销毁的对象(称之为x),该函数   被调用的是构造函数或析构函数类中的最终覆盖,而不是在更派生的类中覆盖它

如果您在A构造函数中,此时您的对象为A,则调用是否来自B构造函数无关紧要。

因此始终会调用A::foo

答案 2 :(得分:0)

A调用B构造函数时,B尚未构建,因此不会虚拟调用A::foo

您可以创建一个函数来创建和初始化您的对象:

struct Base
{
    virtual ~Base();
    virtual void init();
};

struct D : Base
{
    void init() override;
};

D make_D()
{
    D d;
    d.init();
    return d;
}

答案 3 :(得分:0)

使用虚拟表解析对虚拟功能的调用。具有至少一个虚函数(及其所有派生类)的任何类都将具有虚拟表(在本例中为A和B),并且该虚拟表将按照它们的顺序包含所有虚函数的地址。声明。当创建任何此类的对象时,该对象包含指向虚拟表的隐藏指针vptr。因此,首先使用vptr转到虚拟表,然后添加被调用函数的偏移量以获取函数的地址,然后使用此地址调用函数,从而解决虚函数调用。现在重要的是,vptr在类的构造函数中初始化,在特定的构造函数中,它将指向该特定类的虚拟表。在这种情况下,当创建B的对象时,A的构造函数中的vptr(首先调用基类构造函数)将指向A的虚拟表,并且当调用B的构造函数时,vptr将仅指向虚拟B.表示在A的构造函数中,vptr指向A的虚拟表。因此,当你调用foo()时,编译器将转到A的虚拟表,获取foo()的地址,在这种情况下是A的foo()并调用此函数。这就是我们通常说虚拟机制在构造函数中不起作用的原因。原因是vptr没有完全初始化,也没有指向派生类最多的vtable。 我希望这会有所帮助。