mercredi 16 avril 2014

C++ et Java : utilisation de la classe de base virtuelle - Stack Overflow


I have some doubts while comparing C++ and Java multiple inheritance.



  1. Even Java uses multiple, multi-level inheritance through interfaces - but why doesnt it use anything like a virtual base class as in C++ ? Is it because the members of a java interface are being ensured one copy in memory (they are public static final), and the methods are only declared and not defined ?


  2. Apart from saving memory, is there any other use of virtual classes in C++ ? Are there any caveats if I forget to use this feature in my multiple inheritance programs ?


  3. This one is a bit philosophical - but why didnt the C++ developers made it a default to make every base class, virtual ? What was the need of providing flexibility ?



Examples will be appreciated. Thanks !!




1) Java interfaces dont have attributes. One reason for virtual base classes in c++ is to prevent duplicate attributes and all the difficulties associated with that.


2) There is at least a slight performance penalty for using virtual base classes in c++. Also, the constructors become so complicated, that it is advised that virtual base classes only have no-argument constructors.


3) Exactly because of the c++ philosphy: One should not require a penalty for something which one may not need.





  1. Sorry - not a Java programmer, so short on details. Still, virtual bases are a refinement of multiple inheritance, which Java designers always defended ommiting on the basis that it's overly complicated and arguably error-prone.


  2. virtual bases aren't just for saving memory - the data is shared by the different objects inheriting from them, so those derived types could use it to coordinate their behaviour in some way. They're not useful all that often, but as an example: object identifiers where you want one id per most-derived object, and not to count all the subobjects. Another example: ensuring that a multiply-derived type can unambiguously map / be converted to a pointer-to-base, keeping it easy to use in functions operating on the base type, or to store in containers of Base*.


  3. As C++ is currently Standardised, a type deriving from two classes can typically expect them to operate independently and as objects of that type tend to do when created on the stack or heap. If everything was virtual, suddenly that independence becomes highly dependent on the types from which they happen to be derived - all sorts of interactions become the default, and derivation itself becomes less useful. So, your question is why not make the default virtual - well, because it's the less intuitive, more dangerous and error-prone of the two modes.





1.Java multiple inheritance in interfaces behaves most like virtual inheritance in C++. More precisely, to implement java-like inheritance model in c++ you need to use c++ virtual base classes.


However, one of the disadvantages of c++ virtual inheriritance (except of small memory and performance penalty) is the impossibility to static_cast<> from base to derived, so rtti (dynamic_cast) need to be used (or one may provide "hand made" virtual casting functions for child classes if a list of such child classes are known in advance)


2.if you forget "virtual" qualifier in inheritance list, it usually lead to compiler error since any casting frome drived to base class becomes ambigious


3.Philosophical questions usually are quite dificult to answer... c++ is a multiparadigm (and multiphilosophical) language and doesn't impose any philosophical decisions. You may use virtual inheritance whenever possible in you own projects, and (you are rioght) it has a good reason. But such a maxima may be unacceptable for others, so universal c++ tools (standard and other widely used libraries) should be (if possible) free of any particular philosophical conventions.




I'm working on an open source project which basically is translating a large C++ library to Java. The object model of the original creature in C++ can be pretty complicated sometimes. More than necessary, I'd say... which was more or less the motto of Java designers... well... this is another subject.


The point is that I've written an article which shows how you can circumvent type erasure in Java. The article explains well how it can be done and, in the end how your source code can eventually resemble C++ very closely.


http://www.jquantlib.org/index.php/Using_TypeTokens_to_retrieve_generic_parameters


An immediate implication of the study I've done is that it would be possible to implement virtual base classes in your application, I mean: not in Java, not in the language, but in your application, via some tricks, or a lot of tricks to be more precise.


In case you do have interest for such kind of black magic, the lines below may be useful for you somehow. Otherwise certainly not.


Ok. Let's go ahead.


There are several difficulties in Java: 1. Type erasure (solved in the article) 2. javac was not designed to understand what a virtual base class would be; 3. Even using tricks you will not be able to circumvent difficulty #2, because this difficulty appears at compilation time.


If you'd like to use virtual base classes, you can have it with Scala, which basically solved difficulty #2 by exactly creating another compiler, which fully understands some more sophisticated object models, I'd say.


if you'd like to explore my article and try to "circunvent" virtual base classes in pure Java (not Scala), you could do something like I explain below:


Suppose that you have something like this in C++:


template<Base>
public class Extended : Base { ... }

It could be translate to something like this in Java:


public interface Virtual<T> { ... }

public class Extended<B> implements Virtual<B> { ... }

OK. What happens when you instantiate Extended like below?


Extended extended = new Extended<Base>() { /* required anonymous block here */ }

Well.. basically you will be able to get rid of type erasure and will be able to Obtain type information of Base inside your class Extended. See my article for a comprehensive explanation of the black magic.


OK. Once you have type of Base inside Extended, you can instantiate a concrete implementation of Virtual.


Notice that, at compile time, javac can verify types for you, like in the example below:


public interface Virtual<Base> {
public List<Base> getList();
}

public class Extended<Base> implements Virtual<Base> {
@Override
public List<Base> getList() {
// TODO Auto-generated method stub
return null;
}
}

Well... despite all effort to implement it, in the end we are doing badly what an excellent compiler like scalac does much better than us, in particular it is doing its job at compile time.


I hope it helps... if not confused you already!



I have some doubts while comparing C++ and Java multiple inheritance.



  1. Even Java uses multiple, multi-level inheritance through interfaces - but why doesnt it use anything like a virtual base class as in C++ ? Is it because the members of a java interface are being ensured one copy in memory (they are public static final), and the methods are only declared and not defined ?


  2. Apart from saving memory, is there any other use of virtual classes in C++ ? Are there any caveats if I forget to use this feature in my multiple inheritance programs ?


  3. This one is a bit philosophical - but why didnt the C++ developers made it a default to make every base class, virtual ? What was the need of providing flexibility ?



Examples will be appreciated. Thanks !!



1) Java interfaces dont have attributes. One reason for virtual base classes in c++ is to prevent duplicate attributes and all the difficulties associated with that.


2) There is at least a slight performance penalty for using virtual base classes in c++. Also, the constructors become so complicated, that it is advised that virtual base classes only have no-argument constructors.


3) Exactly because of the c++ philosphy: One should not require a penalty for something which one may not need.




  1. Sorry - not a Java programmer, so short on details. Still, virtual bases are a refinement of multiple inheritance, which Java designers always defended ommiting on the basis that it's overly complicated and arguably error-prone.


  2. virtual bases aren't just for saving memory - the data is shared by the different objects inheriting from them, so those derived types could use it to coordinate their behaviour in some way. They're not useful all that often, but as an example: object identifiers where you want one id per most-derived object, and not to count all the subobjects. Another example: ensuring that a multiply-derived type can unambiguously map / be converted to a pointer-to-base, keeping it easy to use in functions operating on the base type, or to store in containers of Base*.


  3. As C++ is currently Standardised, a type deriving from two classes can typically expect them to operate independently and as objects of that type tend to do when created on the stack or heap. If everything was virtual, suddenly that independence becomes highly dependent on the types from which they happen to be derived - all sorts of interactions become the default, and derivation itself becomes less useful. So, your question is why not make the default virtual - well, because it's the less intuitive, more dangerous and error-prone of the two modes.




1.Java multiple inheritance in interfaces behaves most like virtual inheritance in C++. More precisely, to implement java-like inheritance model in c++ you need to use c++ virtual base classes.


However, one of the disadvantages of c++ virtual inheriritance (except of small memory and performance penalty) is the impossibility to static_cast<> from base to derived, so rtti (dynamic_cast) need to be used (or one may provide "hand made" virtual casting functions for child classes if a list of such child classes are known in advance)


2.if you forget "virtual" qualifier in inheritance list, it usually lead to compiler error since any casting frome drived to base class becomes ambigious


3.Philosophical questions usually are quite dificult to answer... c++ is a multiparadigm (and multiphilosophical) language and doesn't impose any philosophical decisions. You may use virtual inheritance whenever possible in you own projects, and (you are rioght) it has a good reason. But such a maxima may be unacceptable for others, so universal c++ tools (standard and other widely used libraries) should be (if possible) free of any particular philosophical conventions.



I'm working on an open source project which basically is translating a large C++ library to Java. The object model of the original creature in C++ can be pretty complicated sometimes. More than necessary, I'd say... which was more or less the motto of Java designers... well... this is another subject.


The point is that I've written an article which shows how you can circumvent type erasure in Java. The article explains well how it can be done and, in the end how your source code can eventually resemble C++ very closely.


http://www.jquantlib.org/index.php/Using_TypeTokens_to_retrieve_generic_parameters


An immediate implication of the study I've done is that it would be possible to implement virtual base classes in your application, I mean: not in Java, not in the language, but in your application, via some tricks, or a lot of tricks to be more precise.


In case you do have interest for such kind of black magic, the lines below may be useful for you somehow. Otherwise certainly not.


Ok. Let's go ahead.


There are several difficulties in Java: 1. Type erasure (solved in the article) 2. javac was not designed to understand what a virtual base class would be; 3. Even using tricks you will not be able to circumvent difficulty #2, because this difficulty appears at compilation time.


If you'd like to use virtual base classes, you can have it with Scala, which basically solved difficulty #2 by exactly creating another compiler, which fully understands some more sophisticated object models, I'd say.


if you'd like to explore my article and try to "circunvent" virtual base classes in pure Java (not Scala), you could do something like I explain below:


Suppose that you have something like this in C++:


template<Base>
public class Extended : Base { ... }

It could be translate to something like this in Java:


public interface Virtual<T> { ... }

public class Extended<B> implements Virtual<B> { ... }

OK. What happens when you instantiate Extended like below?


Extended extended = new Extended<Base>() { /* required anonymous block here */ }

Well.. basically you will be able to get rid of type erasure and will be able to Obtain type information of Base inside your class Extended. See my article for a comprehensive explanation of the black magic.


OK. Once you have type of Base inside Extended, you can instantiate a concrete implementation of Virtual.


Notice that, at compile time, javac can verify types for you, like in the example below:


public interface Virtual<Base> {
public List<Base> getList();
}

public class Extended<Base> implements Virtual<Base> {
@Override
public List<Base> getList() {
// TODO Auto-generated method stub
return null;
}
}

Well... despite all effort to implement it, in the end we are doing badly what an excellent compiler like scalac does much better than us, in particular it is doing its job at compile time.


I hope it helps... if not confused you already!


0 commentaires:

Enregistrer un commentaire