3
votes

Class foo act as interface, it has a pure virtual function and also provide some public overloaded function with same name for convenience so that derived class won't need to provide them in every implementation.

But since derived class must override the pure virtual function, it hides foo's public function.
I tried with "using foo::A", but it won't work because "using" will bring all function including the private one and result in compiler error "error C2876: 'foo' : not all overloads are accessible".

class foo
{
private:
    virtual void A(int a)=0;
public:
    void A()
    {
        A(1000);
    }
    void A(int a, int b)
    {
        A(a+b);
    }

};

class bar : public foo
{
private:
    virtual void A(int a)
    {
        cout << a << "\n";
    }

};

int main()
{
    bar x;
    x.A();
    return 0;
}

I know I can redefine every overloaded function in every class which derived from foo, but this defeat the purpose of convenience.
Or I can cast bar to foo before calling A(), but this approach will get confused since I need to remember which function is define in which class. For example:

class foo
{
private:
    virtual void A(int a)=0;
public:
    void A()
    {
        A(1000);
    }
    void A(int a, int b)
    {
        A(a+b);
    }
};

class bar : public foo
{
private:
    virtual void A(int a)
    {
        cout << "bar:" << a << "\n";
    }
public:
    void A(int a, int b, int c)
    {
        A(a+b+c);
    }
};

class foobar : public bar
{
private:
    virtual void A(int a)
    {
        cout << "foobar:" << a << "\n";
    }
};

int main()
{
    foobar x;
    x.foo::A();
    x.bar::A(1,2,3);
    return 0;
}

I need to clearly remember A withouth argument come from foo, and A with three arguments come from bar. This is also not good for convenience.

1
Name the private virtual function Aimpl.Tadeusz Kopec
Unless I'm missing something, "not all overloads are accessible" is because you've put the pure virtual function in the base class's private section. Change it to being protected and the child classes should then be able to implement it.TheDarkKnight
@Merlin069 Private virtuals can be implemented by child classes. These classes can then define what they do, but not when they're called (that's the job of the public non-virtual which can't be overloaded). Check the Non-virtual-interface idiomJBL
@JBL, that's really interesting, thanks for the link.TheDarkKnight

1 Answers

3
votes

When using the non virtual interface idiom, it's safer, and more explicit, to name the two functions (the public non-virtual and the private virtual) differently.

This shows well what the code does, and would solve your problem:

class foo
{
private:
    virtual void doA(int a)=0;
public:
    void A()
    {
        doA(1000);
    }
    void A(int a, int b)
    {
        doA(a+b);
    }

};

And of course don't forget to change in the hierarchy.