Redefining the visibility of virtual functions in their subclasses

Hi Everyone,

I came across this problem recently. If I have some abstract interface and a class that implements it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class IFoo
{
public:
    virtual ~IFoo() {}
    virtual void ~Func() = 0;
};

class Foo : public IFoo
{
public:
    Foo() {}
    virtual ~Foo() {}
private:
    void Func() {}
};

IFoo * p1 = new Foo();
Foo * p2 = new Foo();

p1->Func();  // fine, because public in IFoo
p2->Func();  // compiler error, because private in Foo 


In fact I did a little more experimentation after discovering this and found out that you redefine the visibility of any virtual function in a subclass (private to public etc). The only time you will get a compiler error for calling a private function is when the instance you are calling from defines it as private.

My question is: Let's say that you want to enforce that you can't call Func() from anything but a pointer to the IFoo, is it a valid design strategy to hide it in the concrete class when it is public in the interface?

I know I'm probably violating some sacred c++ rule of good practice, but try as I might I couldn't find anything about it in books or online yet. Could someone point me to Meyer's or Sutter & Alexandrescu item that will set me straight and whack me over the head?

Many thanks :)
Last edited on
I know I'm probably violating some sacred c++ rule of good practice


You are. Inheritance forms an "is a" relationship. The Child "is a" Parent. If Poodle is derived from Dog, then a Poodle "is a" Dog.

Following that logic, anything you can do with a dog, you can also do with a poodle.


My question is: Let's say that you want to enforce that you can't call Func() from anything but a pointer to the IFoo,


You shouldn't need/want to do this. Since Foo "is an" IFoo, anything you can do with an IFoo you should also be able to do with a Foo -- otherwise you break the "is a" relationship.

Even if somehow what you wanted to do was possible, it would be easily side-stepped / abused.

Consider the following:

1
2
3
4
5
6
7
8
9
10
Foo f;

// what's the difference between this:
f.Func();

// and this?:
IFoo* p = &f;
p->Func();

// why allow one and not the other?  It's nonsense. 
Topic archived. No new replies allowed.