Overriding rules in C++ - java

Coming from a Java perspective I was surprised to find that you can only override base methods that have the virtual keyword.
In Java you use the final keyword to declare that a method can't be overridden.
I had the idea in my head that you only rarely want to prohibit overriding so that someone can extend your class how they see fit.
So in C++ if you feel that someone might want to at some stage inherit from your class (maybe years later someone thinks its a cool idea) do you make all your methods virtual?
Or is there some critical reason for wanting to prohibit this in C++ that I am unaware of?
for Reference this was the experimenting i did in each language:
Java
public class Base {
void doSomething(){
System.out.println("Doing the base thing");
}
}
public class Derived extends Base {
void doSomething(){
System.out.println("Doing the derived thing");
}
public static void main(String... argv){
Base object = new Derived();
object.doSomething();
}
}
C++
class Base
{
public:
Base(void);
~Base(void);
virtual void doSomething();
};
void Base::doSomething(){
std::cout << "I'm doing the base thing\n" << std::endl;
}
class Derived :
public Base
{
public:
Derived(void);
~Derived(void);
void doSomething();
};
void Derived::doSomething(){
std::cout << "I'm doing the dervied thing" << std::endl;
}
int main(void){
Base * object = new Derived;
object->doSomething();
return 0;
}

duffymo and Als are steering you in the right direction. I just wanted to comment on one thing you said:
So in C++ if you feel that someone might want to at some stage inherit
from your class (maybe years later someone thinks its a cool idea) do
you make all your methods virtual?
From a software engineering perspective: if you don't have an immediate use for inheritance and aren't using interfaces, then I don't recommend declaring your methods virtual.
Virtual methods come with an ever so slight performance degradation. For non-critical code paths the perf impact is likely negligible. But for class methods that get invoked a lot, it can add up. The compiler can't do as much inlining and direct linkage. Instead, the virtual method to be invoked has to be looked up in the v-table array at runtime.
When someone on my coding team starts off a design conversation with "someone might want at some point later..." that's when my "future proofing" anti-pattern alarm goes off. Designing for extensibility is one thing, but "features for the future" should be put off until then.
And besides - the guy years later who thinks it's a cool idea - Let him be the one to own converting the class methods to be virtual. You'll be onto bigger projects by then anyway. :)

Yes, in C++ a class method can only be overidden if it is marked virtual in Base class.
If your class is made for inheritance and your class method is meant to provide different behaviors for Base and derived then mark the method as virtual.
Good Read:
When to mark a function in C++ as a virtual?

Yes, you'd have to make all your methods virtual.
Java took the position that everything was fair game to override by default, and that prohibiting it required action. C++ and C# take the opposite view.

You can override a method in a base-class even without virtual.
Take this little program for example:
#include <iostream>
struct A
{
void m()
{ std::cout << "A\n"; }
virtual void n()
{ std::cout << "A\n"; }
};
struct B : public A
{
void m()
{ std::cout << "B\n"; }
virtual void n()
{ std::cout << "B\n"; }
};
int main()
{
A a;
a.m();
a.n();
B b;
b.m();
b.n();
A &c = b;
c.m();
c.n();
}
The output from the program is:
A
A
B
B
A
B
As you can see, the method B::m overrides the same method in A. But that only works when using an exact instance of B. In the third case, when using a reference to the base class you need virtual to make it work.

Programmers coming from languages where virtual functions are the default tend to be surprised that C++ has the reverse choice of defaults, i.e. non-virtual is the default. Note, however, that the contract of a [concrete] virtual function is a lot harder to document and test because there are actually two different contracts involved:
the contract of all overriding functions, i.e. what the function conceptually does
the contract of what the concrete function happens to do
Documenting only one of these won't really cut it because the other half isn't clear at all. This also means that you can't glance from a specific implementation what the actual contract is (assuming you are in the not so untypical situation that the documentation is provided by the source).

Related

Calling private member function in C++ [duplicate]

This question already has answers here:
Overriding public virtual functions with private functions in C++
(7 answers)
Changing Function Access Mode in Derived Class
(4 answers)
Closed 7 years ago.
I came from Java where it's not allowed to decrease access modifiers in derived classes. For instnace, the following is not compile in Java:
public class A{
public void foo(){ }
}
public class B extends A{
#Override
private void foo(){ } //compile-error
}
But, in C++ it's fine:
struct A {
A(){ }
virtual ~A(){ }
A(A&&){ }
public:
virtual void bar(){ std::cout << "A" << std::endl; }
};
struct B : public A{
private:
virtual void bar(){ std::cout << "B" << std::endl; }
};
int main()
{
A *a = new B;
a -> bar(); //prints B
}
DEMO
Where might it be useful? Moreover, is it safe to do so?
As you observed, the access specifier works based on the type of the pointer, not based on the dynamic type. So specifying private in B in this case simply means the functions cannot be accessed through a pointer to B. This could therefore be useful in keeping things locked down in cases where the client should not being using pointers to B (or creating B's on the stack). Basically, in cases where B's constructor is private and you create B's (and possibly other children of A) through a factory that returns a unique_ptr<A>. In this case, you could just specify all of B's methods as private. In principle this prevents the client from "abusing" the interface by dynamic casting the unique_ptr downwards and then accessing B's interface directly.
I don't really think this should be done though; it's a more Java-y approach than C++. In general if the client wants to use a derived object on the stack instead of on the heap through a base class pointer, they should be able. It gives better performance and it's easier to reason about. It also works better in generic code.
Edit: I think I should clarify. Consider the following code:
enum class Impl {FIRST, SECOND, THIRD};
unique_ptr<A> create(Impl i) {
...
}
Suppose this is the only way to create concrete instances that use A's interface. I could desire perhaps that the derived classes are pure implementation details. For instance, I could implement each of the three implementations in a different class, then later decide that two of the three can be lumped together into one class with different options, and so on. It's none of the user's business; their world is just A's interface plus the create function. But now suppose a user happens to look at the source and knows that the FIRST implementation is implemented using B. They want better performance, so they do this:
auto a = create(Impl::FIRST);
auto b = dynamic_cast<B *>(a.get());
// Use b below, potentially avoiding vtable
If a user has code like this, and you eliminate or rename the class B, their code will break. By making all of B's methods private, you make the b pointer useless to the user, ensuring that they use the interface as intended.
As I said before, I don't particularly advocate programming this way in C++. But there may be situations where you really do need the derived classes to be pure implementation details; in those cases changing the access specifier can help enforce it.

What is C++11's equivalent of Java's instanceof

I want to know what the modern C++11 equivalent of Java's instanceof. I have seen this SO post but it is quite old and was wondering if there's a more modern, better solution in C++11?
I was hoping there's a possibility of using a switch construct without having to resort to a manual enum class.
class A {
};
class B : public A {
}
class C : public A {
}
on_event(A& obj)
{
switch (obj) {
case A:
case B:
case C:
}
}
My base class does not have any virtual methods or functions. I am representing an expression tree for a parser and the base class is just a polymorphic holder - like an ADT in Haskell/OCaml.
The same answer still applies, and has always been like this in C++:
if (C * p = dynamic_cast<C *>(&obj))
{
// The type of obj is or is derived from C
}
else
{
// obj is not a C
}
This construction requires A to be polymorphic, i.e. to have virtual member functions.
Also note that this behaviour is different from comparing typeid(obj) == typeid(C), since the latter tests for exact type identity, whereas the dynamic cast, as well as Java's instanceof, only test for the target type to be a base class of the type of the most-derived object.
In C++ plain old data (POD) has no runtime type information. The classes described all take exactly 1 byte, and have identical runtime representations in any compiler with the empty base class optimization.
As such what you want cannot be done.
Adding a virtual destructor to the base class adds in RTTI, and dynamic_cast support.
Adding an enum or int field to the base that gets initialized differently for each derived class also works.
Yet another option is to create a template function, and store a pointer to it, like so:
using my_type_id=void(*)();
template<class>void get_my_type_id_helper(){};
template<class T> my_type_id get_my_type_id(){return get_my_type_id_helper<T>;}
and then storing a my_type_id in A initialized appropriately. This is reinventing RTTI, and as you want more features you will approach C++ RTTI overhead.
In C++ you only pay for what you ask for: you can ask for classes without RTTI, which you did, and get it.
RTTI is Run Time Type Information. POD is plain old data, a C++03 term. Many classes are not POD: the easy way is to add a virtual destructor. C++11 has more fine grained standard layout and aggregate terms.
Technically RTTI and POD are not opposites of each other: there are classes with no RTTI that are not POD.
Note that MSVC has options to not generate RTTI and its aggressive Comdat folding can break the manual RTTI I did above, in both cases in violation of the standard.
Maybe you are interested in the answer I've posted inside your mentioned old SO post.
https://stackoverflow.com/a/49296405/1266588
The answer presents an implementation of instanceof without the usage of dynamic_cast based on C++11, template metaprogramming and RTTI. A small performance measurement application demonstrates that it is more efficient than dynamic_cast if you use compiler optimization.
Don't do that. In most cases you should review your design when you ask for instanceof or dynamic_cast.
Why? You are most likely violating Liskov's substitiontin principle.
How about this approach:
class A {
public:
virtual void action();
virtual ~A();
};
class B : public A {
public: void action() override;
};
class C : public A {
public: void action() override;
};
void on_event(A& obj)
{
obj.action();
}
Note that as #Yakk pointed out you need at least one virtual method anyway to get dynamic polymorphism. And there is a rule that says: When you have at least one virtual method, always also write a virtual destructor in the base class.
You can do all this with templates and specialization or type tagging but I take from your question -- coming from Java -- you don't want to go there yet. You really like virtual methods, don't you? Sorry, that you have to mark them in C++.
If you're willing to limit yourself to types known at compile-time (rather than working through pointers on instances of classes with vtables) - then C++11 and later does have an instanceof equivalent: It is std::is_base_of.
You might also want to check out std::is_convertible and std::is_same.

java final methods vs c++ nonvirtual functions

are java final methods and c++ nonvirtual methods different or the same? How?
They are different.
C++ non-virtual methods are not dispatched, and do not override anything.
Java final methods are dispatched, and can override methods in their classes superclasses.
However, they are the similar in the respect that neither C++ non-virtual methods or Java final methods can be overridden. They are also similar in the sense that if you have some object whose static type is the type in question, the runtime system does not need to dispatch the method call.
To illustrate the difference, consider these two Java classes:
public class A {
public String toString() {
return "A";
}
}
public class B extends A {
public final String toString() {
return "B";
}
}
A a = ...
B b = ...
a.toString(); // could call A.toString() or B.toString() - dispatch
b.toString(); // could only call B.toString() - no dispatch required
// but it will behave the same as if dispatching had occurred.
In the C++ equivalent where B::toString() was non-virtual, I believe a.toString() could not dispatch to B::toString(). (I'm a bit rusty on my C++ ... )
(In fact, the Java JIT compiler is capable of detecting cases where virtual dispatching is not needed ... without you declaring classes or methods as final. Thus, the true purpose of final is to specify that a method shall not be overridden or a class shall not be extended ... and have the Java compiler check this for you.)
You can still declare non-virtual member functions with the same signature in inheriting classes in C++, where-as Java explicitly forbids declaring methods with the same signature in which the base class declares that method final. Virtuality in C++ just helps find the correct function to call when dealing with inheritance/polymorphism.
Example:
#include <iostream>
class Base
{
public:
void doIt()
{
std::cout << "from Base.doIt()" << std::endl;
}
};
class Child : public Base
{
public:
void doIt()
{
std::cout << "from Child.doIt()" << std::endl;
}
};
int main()
{
Base a;
a.doIt(); // calls Base.doIt()
Child b;
b.doIt(); // calls Child.doIt()
Base *c = new Base();
c->doIt(); // calls Base.doIt()
Child *d = new Child();
d->doIt(); // calls Child.doIt()
Base *e = new Child();
e->doIt(); // calls Base.doIt()
std::cin.ignore();
return 0;
}
The comparable example in Java using final will result in a compiler error:
public class Base
{
public final void doIt()
{
System.out.println("In Base.doIt()");
}
}
public class Child extends Base
{
public void doIt() // compiler error: Cannot overload the final method from Base
{
System.out.println("In Child.doIt()");
}
}
For more explanation on Polymorphism in C++, see cplusplus.com: Polymorphism
Effictively, though, both methods have similar goals: to prevent overriding of a function in the base class. They just go about it in slightly different ways.
They are very different, in fact, I would say, completely unrelated.
In C++, if a base class has a non-virtual member function, then, you can declare, in a derived class, a non-virtual member function with the same name. The effect will be that the derived class' member function will hide the base class' member function. And no virtual dispatching can occur. As in the following:
struct Base {
void foo() {
std::cout << "Base::foo called!" << std::endl;
};
};
struct Derived : Base {
void foo() {
std::cout << "Derived::foo called!" << std::endl;
};
};
int main() {
Derived d;
d.foo(); //OUTPUT: "Derived::foo called!"
Base* b = &d;
b->foo(); //OUTPUT: "Base::foo called!"
};
The above shows how the member function of the derived class hides the base class function. If you have a pointer to a base class, since the functions are non-virtual, the virtual table is not used to resolve the call and thus, the foo function from the base class will be called. The point here is that, in C++, nothing prevents you from creating another function in the Derived class with the same name (note that a different signature will still cause the hiding of all the base class' member functions with the same name). All you will get is a compiler warning telling you that the member function of the Derived class hides member function(s) of the Base class.
A final member function in Java is completely different. In Java, all member functions are virtual. So you can't turn-off the virtual dispatching like you can in C++. A final member function just means that any subsequent derived class will not be allowed (an error will occur) to declare a member function with the same name (and signature). But virtual dispatch (and thus, overriding, in the dynamically polymorphic sense) still occurs between the interface / base class that declared the original member function and the derived class that marked it as final. It is just that later overriding of the function is strictly forbidden (i.e. trying the above code with foo() marked as final in the Base class would give an error in the declaration of the Derived class, because the foo() there would not be allowed).
As you see, the two concepts are completely different.
In C++, with a non-virtual member function, virtual dispatching does not occur (thus, no "overriding" in the traditional sense) but you are allowed to have derived classes with member functions of the same name (and it can be useful sometimes in "static polymorphism").
In Java, with a final member function, virtual dispatching still occurs, but overriding in subsequent derived classes is strictly forbidden.
Using a virtual vs non-virtual function is C++ can make a performance difference, conversely there may be no performance difference in Java. In Java, marking a method as final it is purely about clarity and maintainability of code (it is not the default behaviour and relatively rarely used), and in C++ non-virtual function are the default behaviour and commonly used in part because they have better performance characteristics.
In Java, the code generated can differ based on how it is used, whereas C++ must produce for correctness at compile time.
e.g. if the JVM detects that a "virtual" method has only one or two implementations common used it can inline those methods or treat a "virtual" method with only one implementation used as if it were final.

Generic inheritance in java

In c++ we can write:
#include <iostream>
class Base1
{
public: void test() { std::cout << "Base 1" << std::endl; }
};
class Base2
{
public: void test() { std::cout << "Base 2" << std::endl; }
};
template<class T>
class Derived: public T
{
};
int main()
{
Derived<Base1> d1;
Derived<Base2> d2;
d1.test();
d2.test();
}
To get templated inheritance.
Can the same be done in java using generics?
Thanks.
Edit: Adding more info about my intentions
In my scenario I have two subclasses, Sprite and AnimatedSprite (which is a subclass of Sprite). The next step is a PhysicalSprite that adds physics to the sprites, but I want it to be able to inherit from both Sprite and AnimatedSprite.
No. C++'s templates are much stronger than Java's generics. Generics in Java are only for ensuring proper typing during compile time and are not present in the generated bytecode - this is called type erasure.
In my scenario I have two subclasses, Sprite and AnimatedSprite (which is a subclass of Sprite). The next step is a PhysicalSprite that adds physics to the sprites, but I want it to be able to inherit from both Sprite and AnimatedSprite.
Inheritance is not the only form of code reuse. This use case can be handled with other patterns as well, such as simple decoration. Consider something akin to the following:
interface Sprite { ... }
class StaticSprite implements Sprite { ... }
class AnimatedSprite implements Sprite { ... }
class PhysicalSprite implements Sprite, Physics {
PhysicalSprite(Sprite inner) { ... }
...
}
PhysicalSprite would in this case delegate the Sprite parts to some Sprite instance provided in the constructor. It would then be free to add its own handling for the Physics part.
Alas, no.
Unlike C++, which can be thought to emit a different class definition for every instantiation of a template, all instantiations of a generic type share the same runtime class in Java, and therefore have the same method definitions. Generics (in Java) are compile-time and not tracked at runtime.
Therefore, the Java Language Specification explictly forbids to specify a type paramater as superclass or implemented interface:
The optional extends clause in a normal class declaration specifies the direct superclass of the current class.
Super: extends ClassType
where ClassType is a qualified or unqualified class name (with optional type arguments)
Workarounds
Use the decorator pattern if you don't need to override methods invoked by the super class.
Generate a dedicated subclass for each instantiation of the template. You can do so at runtime using, for instance, Javassist, or using source code transformations at compile time.
No, not in exact same way. But if you tell us what exactly you want to do, I'm pretty sure there'll be some elegant way to do that. I just don't see any need for templates/generics in your example.
In particular, it looks like Base1 and Base2 might benefit from common interfaces with method test.
Hm.. Do you need decorator?

Virtual functions in constructors, why do languages differ?

In C++ when a virtual function is called from within a constructor it doesn't behave like a virtual function.
I think everyone who encountered this behavior for the first time was surprised but on second thought it made sense:
As long as the derived constructor has not been executed the object is not yet a derived instance.
So how can a derived function be called? The preconditions haven't had the chance to be set up. Example:
class base {
public:
base()
{
std::cout << "foo is " << foo() << std::endl;
}
virtual int foo() { return 42; }
};
class derived : public base {
int* ptr_;
public:
derived(int i) : ptr_(new int(i*i)) { }
// The following cannot be called before derived::derived due to how C++ behaves,
// if it was possible... Kaboom!
virtual int foo() { return *ptr_; }
};
It's exactly the same for Java and .NET yet they chose to go the other way, and is possibly the only reason for the principle of least surprise?
Which do you think is the correct choice?
There's a fundamental difference in how the languages define an object's life time. In Java and .Net the object members are zero/null initialized before any constructor is run and is at this point that the object life time begins. So when you enter the constructor you've already got an initialized object.
In C++ the object life time only begins when the constructor finishes (although member variables and base classes are fully constructed before it starts). This explains the behaviour when virtual functions are called and also why the destructor isn't run if there's an exception in the constructor's body.
The problem with the Java/.Net definition of object lifetime is that it's harder to make sure the object always meets its invariant without having to put in special cases for when the object is initialized but the constructor hasn't run. The problem with the C++ definition is that you have this odd period where the object is in limbo and not fully constructed.
Both ways can lead to unexpected results. Your best bet is to not call a virtual function in your constructor at all.
The C++ way I think makes more sense, but leads to expectation problems when someone reviews your code. If you are aware of this situation, you should purposely not put your code in this situation for later debugging's sake.
Virtual functions in constructors, why do languages differ?
Because there's no one good behaviour. I find the C++ behaviour makes more sense (since base class c-tors are called first, it stands to reason that they should call base class virtual functions--after all, the derived class c-tor hasn't run yet, so it may not have set up the right preconditions for the derived class virtual function).
But sometimes, where I want to use the virtual functions to initialize state (so it doesn't matter that they're being called with the state uninitialized) the C#/Java behaviour is nicer.
I think C++ offers the best semantics in terms of having the 'most correct' behavior ... however it is more work for the compiler and the code is definitiely non-intuitive to someone reading it later.
With the .NET approach the function must be very limited not to rely on any derived object state.
Delphi makes good use of virtual constructors in the VCL GUI framework:
type
TComponent = class
public
constructor Create(AOwner: TComponent); virtual; // virtual constructor
end;
TMyEdit = class(TComponent)
public
constructor Create(AOwner: TComponent); override; // override virtual constructor
end;
TMyButton = class(TComponent)
public
constructor Create(AOwner: TComponent); override; // override virtual constructor
end;
TComponentClass = class of TComponent;
function CreateAComponent(ComponentClass: TComponentClass; AOwner: TComponent): TComponent;
begin
Result := ComponentClass.Create(AOwner);
end;
var
MyEdit: TMyEdit;
MyButton: TMyButton;
begin
MyEdit := CreateAComponent(TMyEdit, Form) as TMyEdit;
MyButton := CreateAComponent(TMyButton, Form) as TMyButton;
end;
I have found the C++ behavior very annoying. You cannot write virtual functions to, for instance, return the desired size of the object, and have the default constructor initialize each item. For instance it would be nice to do:
BaseClass() {
for (int i=0; i<virtualSize(); i++)
initialize_stuff_for_index(i);
}
Then again the advantage of C++ behavior is that it discourages constuctors like the above from being written.
I don't think the problem of calling methods that assume the constructor has been finished is a good excuse for C++. If this really was a problem then the constructor would not be allowed to call any methods, since the same problem can apply to methods for the base class.
Another point against C++ is that the behavior is much less efficient. Although the constructor knows directly what it calls, the vtab pointer has to be changed for every single class from base to final, because the constructor might call other methods that will call virtual functions. From my experience this wastes far more time than is saved by making virtual functions calls in the constructor more efficient.
Far more annoying is that this is also true of destructors. If you write a virtual cleanup() function, and the base class destructor does cleanup(), it certainly does not do what you expect.
This and the fact that C++ calls destructors on static objects on exit have really pissed me off for a long time.

Categories