开发者

C++ Virtual Const Function

Given the following snippet,

class Base
{
public:
    virtual void eval() const
    {
        std::cout<<"Base Const Eval\n";
    }
};

class Derived:public Base
{
public:
    void eval()
    {
        std::cout<<"Derived Non-Const Eval\n";
    }
};

int main()
{

    Derived d;
    Base* pB=&d;

    pB->eval(); //This will call the Base eval()

    return 0;
}

Why the pB->开发者_JS百科eval() will call the Base::eval()?

Thank you


In your Derived class, the prototype for eval doesn't match the one for the virtual function in Base. So it won't override the virtual function.

Base::eval() const;
Derived::eval(); //No const.

If you add the const for Derived::eval(), you should get virtual behavior.


You can translate in your mind:

virtual void Base::eval() const;
void Derived::eval() ;

to

void eval(const Base *this, size_t vtable_offset); 
void eval(Derived *this);

and see by inspection how little the second matches the signature of the first.


This is because one is declared const and the other isn't. One function is being hidden by the other. The function in Derived is hiding the one in Base because they have the same name while they aren't the same function.

My compiler gives a warning here, does yours?


$10.3/2- "If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list (8.3.5), cv-qualification, and refqualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides111 Base::vf."

111) A function with the same name but a different parameter list (Clause 13) as a virtual function is not necessarily virtual and does not override. The use of the virtual specifier in the declaration of an overriding function is legal but redundant (has empty semantics). Access control (Clause 11) is not considered in determining overriding.

As an aside, note that it does not talk about access specifications. So base class and derived class access specifiers for the overridden function could be different

This means that Derived::eval does not override Base::eval as their cv qualifications differ.


The const is part of the function signature. In order to override a function the override must have exactly the same signature as the base version - in this case it does not.

Consider that the calling code doesn't need to know anything about Derived - it is calling a const function on a Base. You wouldn't expect that call to wind up in a non-const function which might change stuff about the class.


In C++0x, the situation is detectable at compile time using the base_check and override keywords. Excerpt from wikipedia:

The [[base_check]] attribute on a class/struct means that any implicit overriding will give rise to a compiler error. Any overriding must be explicitly marked with the [[override]] attribute.

Most probably (not very sure about the syntax):

class Derived [[base_check]] : public Base {

    virtual void eval [[override]] () {
        ....
    }
};
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜