eranpeer / FakeIt

C++ mocking made easy. A simple yet very expressive, headers only library for c++ mocking.
MIT License
1.22k stars 170 forks source link

Overloaded function in derived class hides base class function #284

Closed otrempe closed 1 year ago

otrempe commented 1 year ago
class IBase
{
public:
    virtual ~IBase() = default;

    virtual void MyOverloadedFunction( int )            = 0;
    virtual void MyConstOverloadedFunction( int ) const = 0;
};

class IDerived : public IBase
{
public:
    virtual void MyOverloadedFunction( double )            = 0;
    virtual void MyConstOverloadedFunction( double ) const = 0;
};

{
    fakeit::Mock< IDerived > mock;
    fakeit::When( OverloadedMethod( mock, MyOverloadedFunction, void( double ) ) );
    fakeit::When( ConstOverloadedMethod( mock, MyConstOverloadedFunction, void( double ) ) );

    fakeit::When( OverloadedMethod( mock, MyOverloadedFunction, void( int ) ) );
    fakeit::When( ConstOverloadedMethod( mock, MyConstOverloadedFunction, void( int ) ) );
}

error C2664: 'void (cdecl IDerived::* fakeit::Prototype<void (int)>::MemberType::get(void (cdecl IDerived:: )(int)))(int)': cannot convert argument 1 from 'void (__cdecl IDerived:: )(double)' to 'void (__cdecl IDerived::* )(int)' note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast error C2672: 'fakeit::Mock::stub': no matching overloaded function found error C2672: 'operator __surrogate_func': no matching overloaded function found

error C2664: 'void (cdecl IDerived::* fakeit::Prototype<void (int)>::MemberType::getconst(void (cdecl IDerived:: )(int) const))(int) const': cannot convert argument 1 from 'void (__cdecl IDerived:: )(double) const' to 'void (__cdecl IDerived::* )(int) const' note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast error C2672: 'fakeit::Mock::stub': no matching overloaded function found error C2672: 'operator __surrogate_func': no matching overloaded function found

otrempe commented 1 year ago

The workaround is to redeclare the base class function in the derived class

FranckRJ commented 1 year ago

That's how C++ works, it isn't an issue with the library.

You don't need to redeclare the function, you can also "import" it.

class IDerived : public IBase
{
public:
    using IBase::MyOverloadedFunction;
    using IBase::MyConstOverloadedFunction;
    virtual void MyOverloadedFunction( double )            = 0;
    virtual void MyConstOverloadedFunction( double ) const = 0;
};
otrempe commented 1 year ago

Non virtual function should hide base class function, but virtual function should be fine. This scheme compiles fine on all compiler versions I tried without importing base class functions.

FranckRJ commented 1 year ago

The function being virtual or not change nothing, it's the same rules.

As you can see : https://godbolt.org/z/6f4h4nPMW

otrempe commented 1 year ago

You're right, I was fooled by my test using the wrong type for calling the overloaded function.