Private Virtual Method in C++

Why are private virtual methods illegal in C#?

I note that there are two questions here. In the future you might consider posting two questions instead of combining two questions in one. When you combine questions like this often what happens is only the first one gets answered.

The first question is "why are private virtual methods illegal in C#?"

Here are the arguments against the "private virtual methods" feature:

  1. private virtual is only useful when you have a nested derived class. This is a useful pattern, but far less common than the non-nested derived class situation.

  2. If you desire to restrict the ability to override the method in non-nested derived classes then you can do so by restricting the ability of non-nested classes to derive from the base class; make all the base class constructors private. Therefore private virtual is not necessary to prevent overriding; protected virtual is sufficient, because the only derived classes will be nested.

  3. If you desire to restrict the ability to call a method in a non-nested derived class then you can make the method internal virtual and then tell your coworkers to not use that method. It is irritating to have this not be enforced by the compiler, but the compiler does not enforce any other semantic constraint on how a method is supposed to be used either; getting the semantics right is your business, not the compiler's, and you have to enforce that with appropriate code reviews. Therefore private virtual is not necessary to prevent calling; internal virtual plus code reviews is sufficient.

  4. It is possible to implement this pattern already with existing parts:

    abstract class C
    {
    private int CF() { whatever; }
    private Func<int> f;
    public C() { f = CF; }
    private int F() { return f(); }
    private class D : C
    {
    private int DF() { whatever; }
    public D() { f = DF; }
    }

    Now I have a method F which is effectively virtual, but can only be "overridden" by derived nested classes.

Since in every case either protected, internal or protected internal does the trick, private virtual is unnecessary. It's almost never the right thing to do, since you have to be already committed to using the nested derived class pattern. So, the language makes it illegal.

The arguments for are:

There have been times in real code when I've want a virtual method to be a private implementation detail of a class that I want to be extended both by non-nested internal classes and nested internal classes. Having to enforce the invariant that the internal method not be called by my coworkers is vexing; I'd like that to be enforced by the compiler without me having to jump through crazy hoops like making a field of delegate type, etc.

Also, there's simply the matter of consistency and orthogonality. It seems weird that two things that ought to be independent -- accessibility and virtualness -- have an effect on each other unnecessarily.

The arguments against the feature are pretty strong. The arguments for are pretty weak. Therefore, no such feature. I'd personally like it very much, but I totally understand why the design team has never taken me up on it. It's not worth the cost, and I would hate to not ship a better feature because we spent budget on a feature that benefits almost no one.

The second question is "Why in C# are you not able to override a private virtual method in a derived non-nested class?"

There are several reasons.

  1. Because you can only override what you can see. A private method is a private implementation detail of a base class and must not be accessible.

  2. Because allowing that has serious security implications. Remember, in C++ you almost always compile code into an application all at once. You have the source code for everything; everything is essentially "internal" from the C++ perspective most of the time. In C#, that's not at all the case. Third party assemblies can easily get at public types from libraries and produce novel extensions to those classes which can then be used seamlessly in place of instances of the base class. Since virtual methods effectively change the behaviour of a class, any code which depends for security reasons on invariants of that class needs to be carefully designed so that they do not depend on invariants guaranteed by the base class. Restricting accessibility of virtual methods helps ensure that invariants of those methods are maintained.

  3. Because allowing that provides another form of the brittle base class problem. C# has been carefully designed to be less susceptible to the brittle base class problem than other OO languages. If an inaccessible virtual method could be overridden in a derived class then that private implementation detail of the base class becomes a breaking change if altered. Providers of base classes should be free to change their internal details without worrying overmuch that they've broken derived classes which depend on them; ideally only the public, documented interface to a type needs to be maintained when implementation details change.

How can we access to the private virtual method in C++?

As already mentioned, you can only access private members of a class from within the same class or via a friend function of the class.

Since func is neither a member of the class A nor a friend function of class A, then you cannot call the private function foo from func...unless we make some changes.

Observing that you are passing an address of an A object to func and you wish to call the private function foo, then implementing func as a friend function of the A class should be the obvious choice.

#include<iostream>

class A
{
public:
A():var(2){}
virtual ~A(){}
friend int func(A const* a){return a->foo();}
private:
virtual int foo() const{return this->var;}
int var;
};

int main()
{
A a;

std::cout << func(&a) << std::endl;

return 0;
}

Can you override private virtual methods?

You can't even declare private virtual methods. The only time it would make any sense at all would be if you had:

public class Outer
{
private virtual void Foo() {}

public class Nested : Outer
{
private override void Foo() {}
}
}

... that's the only scenario in which a type has access to its parent's private members. However, this is still prohibited:

Test.cs(7,31): error CS0621:
'Outer.Nested.Foo()': virtual or
abstract members cannot be private

Test.cs(3,26): error CS0621:
'Outer.Foo()': virtual or abstract
members cannot
be private

C++: Private virtual functions vs. pure virtual functions

One benefit is in implementing the template method pattern:

class Base {

public :
void doSomething() {
doSomething1();
doSomething2();
doSomething3();
}
private:
virtual void doSomething1()=0;
virtual void doSomething2()=0;
virtual void doSomething3()=0;
};


class Derived : public Base {
private:
virtual void doSomething1() { ... }
virtual void doSomething2() { .... }
virtual void doSomething3() { .... }
}

This allows the derived classes to implement each piece of a certain logic, while the base class determines how to put these pieces together. And since the pieces don't make sense by themselves, they are declared private and so hidden from client code.

Why private virtual member function of a derived class is accessible from a base class

First, as @Eljay notes - printImpl() is a method, albeit virtual, of the Base class. So, it's accessible from the base class. Derived merely provides a different implementation of it. And the whole point of virtual functions is that you can call a subclass' override using a base class reference or pointer.

In other words, private only regards access by subclasses; it's meaningless to keep something private from a class' base class: If a method is at all known to the base class, it must be a method of the base class... a virtual method.

Having said all that - note that the Derived version of printImpl() is effectively inaccessible from print() - when it's invoked within the base class constructor. This is because during that call, the constructed vtable is only that of Base, so printImpl points to Base::printImpl.

I thought private member functions could be called ONLY from the member functions of the same class

And indeed, print() is a member of Base, which invokes printImpl() - another method of Base.

C++ override private pure virtual method as public

According to https://en.cppreference.com/w/cpp/language/virtual#In_detail overriding a base's virtual member function only care about the function name, parameters, const/volatile-ness and ref qualifier. It doesn't care about return type, access modifier or other things you might expect it to care about.

The linked reference also specifically notes that :

Base::vf does not need to be visible (can be declared private, or inherited using private inheritance) to be overridden.

Nothing that I can find explicitly gives permission to do this, but the rules of overriding do not prevent it. It's allowed by virtue of virtual functions and function overriding existing and not disallowing this case.

If you are asking why this is how the language is, you may have to ask the standardization committee.

Purpose of private pure virtual function?

So in general the pattern is to implement the public non-virtual function and the private or protected virtual function, it looks like you have researched this already, but this is generally known as the Template Method Pattern, with more explanations by Herb Sutter here and here.

Whether to make it pure virtual or not depends on your requirements, sometimes there is absolutely no default behavior that makes sense, or you want to force all the subclasses to implement their own version of this virtual function. Sometimes an empty implementation does make sense. Then provide, but what happens is that other implementors might forget to customize their classes, not implementing the virtual class for which you provided a default behavior. It is really a case by case decision that you will have to make.

There are some corner cases in which you will want to provide an implementation for a pure virtual function, Herb Sutter again, lists two, one to provide default behavior but force derived classes to conciously call, and the other is to protect against compiler issues that might get a pure virtual function called.

There are various concerns comming together at the point where your problem lies, in general make virtual functions private or protected, called by a public function (again Template Method Pattern). If derived classes don't need to call a superclasses implementation, make it private. If you want to implement default behavior make it protected and implement the default behavior in a higher class. If you want to force subclasses to implement their own function (independent of wether there is default behavior or not) make it pure virtual.



Related Topics



Leave a reply



Submit