views:

335

answers:

4

If I have in C++:

class A {
    private: virtual int myfunction(void) {return 1;}
}

class B: public A {
    private: virtual int myfunction(void) {return 2;}
}

Then if I remove virtual from the myfunction definition in class B, does that mean that if I had a class C based on class B, that I couldn't override the myfunction since it would be statically compiled?

Also, I'm confused as to what happens when you switch around public, and private here. If I change the definition of myfunction in class B to be public (and the one in class A remains private), is this some sort of grave error that I shouldn't do? I think that virtual functions need to keep the same type so that's illegal, but please let know if that's wrong.

Thanks!

+2  A: 

If You remove virtual from the myfunction definition in class B,

compiler will add this for You. To fill out V-Table for polymorphic types.

!!BUT!!

You will only have access to public members of class A (class B: public A)

the definition :

class B: private A
{

}

Will cause that all (even public) members of class A, will become private for class B. Simplifies You will not have an access to A public members.

To workaround You can declare some friend:

class A
{
    private:
        friend class B;
}

More great info HERE.

bua
Thanks for the quick reply!
Jasie
The answer is a bit confusing for me. From the answer I read that class B can not access public members he inherits from class A, which is then solved by declaring B friend of A. I don't think that would be right. B can access public and protected members from A but users of B can not access public members of A and this will not be solved by the friend declaration. Am I missinterpreting something?
stefaanv
Yes, You've missed the private inheritance from my example.
bua
Okay, then I suggest you reread the info on your link: class B can access all public and protected members from his privately inherited class A, friend or not friend.
stefaanv
+6  A: 

once a function is made virtual in a base class, it will be virtual for every other subclass.

public, protected and private do not affect the virtual nature of functions.

Chris Bednarski
Thank you! Thanks for the visibility info.
Jasie
By making your virtual functions protected or private you can hint to the users of your class if they're required to call them in the subclass or not. http://www.gotw.ca/publications/mill18.htm
Chris Bednarski
+8  A: 

The first definition with 'virtual' is the one that matters. That function from base is from then on virtual when derived from, which means you don't need 'virtual' for reimplemented virtual function calls. If a function signature in a base class is not virtual, but virtual in the derived classes, then the base class does not have polymorphic behaviour.

class Base
{
    public:
    void func(void){ printf("foo\n"); }
};
class Derived1 : public Base
{
    public:
    virtual void func(){ printf("bar\n"); }
};
class Derived2 : public Derived1
{
    public:
    /*  reimplement func(), no need for 'virtual' keyword
        because Derived1::func is already virtual */
    void func(){ printf("baz\n"); } 
};

int main()
{
    Base* b = new Derived1;
    Derived1* d = new Derived2;

    b->func(); //prints foo - not polymorphic
    d->func(); //prints baz - polymorphic
}
Mads Elvheim
Thanks, that was very helpful!
Jasie
You're welcome. I should also add that "Base* b" is actually a Derived1. Use dynamic_cast to perform safe downcasting in situations you need it.
Mads Elvheim
But the authors example covers private members.
bua
@bua : Unlike dependent/independent name lookups when using templates, name lookups of virtual calls are not influenced by access specifiers.
Mads Elvheim
A: 

The behavior of virtual is that it effects which method is called when you have a pointer of one type that points to an object of a subtype. For example:

B* obj = new B;
A* base = obj;

What happens when you call obj->myfunction() depends on whether A declares myfunction to be virtual. If it is not virtual, the reasoning is: we have a pointer of type A, so we call the function defined in A, and the result is 1. If A defines myfunction to be virtual, however, then a look-up is performed at run-time based on the type of the actual object, rather than the type of the pointer; since the object is actually a B, the implementation defined in B is used and the result is 2.

Further information can be found in the C++ FAQ Lite section on virtual functions.

qid