Taligent Logo
Porting Paper
dot_clear
dot_clear

Java Cookbook: Porting C++ to Java

Esoterica

Introduction, Basics, Next Steps, Well-Mannered Objects, Esoterica, Background, Index


The following sections deal with less common constructs in C++.


Primogenitur Entail

Java does not support multiple inheritance. It does support interfaces, which can get you a long way towards replacing multiple inheritance. You can think of interfaces as fully abstract classes, with no data fields and all pure virtual methods. If all but one of the base classes for your class are fully abstract classes, then just turn them into interfaces.

Simple Multiple Inheritance

C++

Java

// Bar is fully abstract
class Bar {
 ...
 void someMethod() = 0;
}

// simple multiple inheritance
class Foo : Fii, Bar {...
// Bar is purely abstract
interface Bar {
 ...
 void someMethod();
}

// simple multiple inheritance
class Foo extends Fii 
          implements Bar {...

If the inheritance is not simple, then you will have to do some more work. First, pick the base class that is most central to the function of the class in question. For each of the other base classes:
  1. define a new interface that each one implements
  2. declare a field of the type of each base in your target class
  3. delegate methods in your target class to the appropriate field

Goto higher levels

C++

Java

// Other base classes
class Bar {
 ...
 void methodA();
}

class Foe {
 ...
 int methodB();
}

// simple multiple inheritance
class Foo : Fii, Bar, Foe {


 ...








}
// Other base classes
class Bar {
 ...
 void methodA();
}

class Foe {
 ...
 int methodB();
}

// simple multiple inheritance
class Foo extends Fii 
          implements BarInterface,
            FoeInterface {...
 ...
 void methodA() {
  bar.methodA();
 }
 void methodB() {
  return foe.methodB();
 }
 private Bar bar = new Bar();
 private Foe foe = new Foe();
}

// Interfaces
interface BarInterface {
 ...
 void methodA();
}

interface FoeInterface {
 ...
 void methodB();
}


Size doesn't matter

You can't use sizeof in Java. You generally only use it when you are doing unions, bit-field manipulations or C-style memory management. You will need to look carefully at the intent to see how to port the code. For example:

Replacing sizeof

C++

Java

x = (Foo*) alloc(sizeof(Foo)*len);
x = new Foo[len];

You will have to remove the bitfield notation, since that is not supported in Java. Generally you can just dispense with the notation. If you really, really need bitfields to save storage, see Shave and a Haircut.


Shave and a Haircut

If you really, really need bitfields to save storage, then you will need to do it yourself, basically by duplicating the code that is behind the use of bitfields in C++. If you are using large numbers of single bits, use java.util.BitSet (Bitset is safer and easier than managing the masks and shifting yourself, but will not save you storage unless you have a significant number of bits.)

Replacing Bitfields

C++

Java

// declaring
struct Foo {
 // ...
 unsigned int z:3;
}
 
 
 
 
 
 
 
 
 
 
 
// using
a = myFoo.z;
z = myFoo.b;
// declaring
class Foo {
 // ...
 public byte getZ() {
  return (xyz & Z_MASK) >>> Z_SHIFT;
 }
 public void setZ() {
  xyz = (b << Z_SHIFT) & Z_MASK
        | xyz & ~Z_MASK;
 }
 private int xyz;
 private final static Z_SHIFT = 17;
 private final static Z_SHIFT = 0x7;
}
 
 
// using
a = myFoo.getZ();
myFoo.setZ(b);

Unions are also excluded from Java. The easiest approach to porting then is just to make the union into a class.

Unions

C++

Java

// declaring
union Foo {
 bool isFiiVsBarr;
 Fii x;
 Barr y;
}
// declaring
class Foo {
 boolean isFiiVsBarr;
 Fii x;
 Barr y;
}

Where they are being used for storage savings, you can sometimes get the same effect by using Object. The only disadvantage is that you are substituting runtime type-checking for compile-time checking.

Where unions are being used for scurrilous casting, you will have to work around it. For example, where such castings are used for hiddent bit-manipulations, you'll have to use the appropriate arithmetic operations, as below. You will have the advantage of having much more portable code in the end, though, without big-endian or little-endian troubles.

Bit Twiddling in Unions

C++

Java

// declaring
union Foo {
 int i;
 char c;
}
 
// using
x.i = 99;
z = x.c;
// declaring
int i;
 
 
 
 
// using
x = 1066;
z = x & 0xFF;   // if C++ was BE
z = x & 0xFF00; // if C++ was LE


Directly to Jail

Well-written C++ code should have very few gotos, if any. There are, however, times where a goto produces less convoluted code: where you need to escape from an inner loop. Although Java has completely eliminated gotos, it has added a construct that replaces their use, and in a much cleaner and less dangerous way. You can name a loop with a label, then use break or continue with that label to escape from an inner block.

Goto end of block

C++

Java

for (int i = 0; i < n; ++i) {
 for (int j = 0; j < m; ++j) {
  if (f(i,j)) {
   goto done;
  }
 }
}
done:
mainLoop:
for (int i = 0; i < n; ++i) {
 for (int j = 0; j < m; ++j) {
  if (f(i,j)) {
   break mainLoop;
  }
 }
}

If your gotos don't follow this pattern, then it is still fairly easy to convert if the gotos don't cross blocks. This is a bit kludgy, but saves your having to go in and figure out this snarled code.

Goto higher levels

C++

Java

{...
 {...
  {...
   goto done;
  ...
  }
 ...
 }
...

}
done:
kludgeLoop: 
while (true) {...
 {...
  {...
   break kludgeLoop;
  ...
  }
 ...
 }
...
break;
}

If your gotos jump into the middle of nested blocks (such as into a switch statement), then you will have no choice but to try to untangle the code.


Java has no friends

Java doesn't have the friend keyword. You can, however, permit access to your privates by any other class in your package by making the access package-private. You do this by omitting the keyword private from your methods or data fields, and ensuring that the former friends are in the same package.

Replacing Friend

C++

Java

class Foo {
 private int foe;
 protected int fii;
 friend class Bar;
}

class Bar {
 private Foo foo;
 public method() {
  ...
  y = foo;
  z = fii;
  ...
 }
}
class Foo {
 int foe;
 protected int fii;
 int getFii() {...}
}

class Bar {
 private Foo foo;
 public method() {
  ...
  y = foo;
  z = getFii();
  ...
 }
}

Notes

  • If you need to allow access to protected fields or methods, then you have to write cover methods that allow package-private access.
  • If you need to have friend access from two different packages, then you are out of luck. Your only choices are:
    • to make the methods or fields public
    • copy the class into both packages (this works for small classes)


Introduction, Basics, Next Steps, Well-Mannered Objects, Esoterica, Background, Index

 

dot_clear dot_clear dot_clear dot_clear dot_clear
navbar
Products Object Resources In the News Company Info Search
 
If you encounter problems with this service please contact webmaster@taligent.com.

© Copyright. All rights reserved. Taligent, Inc., IBM Corp.