I am writing a backend of a compiler of a subset of Java. The backend writes C++ code. There is some hypothetical Java code, though, that I do not known how to translate to C++.
An example problem is shown in the following code. A is extended by B, B is extended by C, and here are respective three header files A.h, B.h and C.h:
#ifndef A_H
#define A_H
class B;
class A {
public: virtual B* get();
}
#endif /* !defined(A_H) */
==========================
#ifndef B_H
#define B_H
#include "A.h"
class C;
class B : public A {
public: virtual C* get();
}
#endif /* !defined(B_H) */
==========================
#ifndef C_H
#define C_H
#include "B.h"
class C : public B {
}
#endif /* !defined(C_H) */
As can be seen, B overrides A's method get(). The overriding method returns a pointer to a respective subclass, which I guess is valid in C++, thanks to covariance.
What I do not know, is the way of informing the compiler, that C is indeed a subclass of B, and thus, that the overriding method is valid.
A forward declaration of C within B.h, just as the one seen in the code, is not enough, as it says nothing about C's superclasses.
An inclusion of C.h within B.h would be circular, as C.h already includes B.h. The latter is needed, because it is not enough to have only a forward declaration of the superclass.
What can be done with that?
EDIT Two remarks.
1 One of the poster claims, that the following is impossible in Java, so I add a Java version:
A.java:
class A {
public B get() {
return null;
}
}
B.java:
class B extends A {
public C get() {
return null;
}
}
C.java:
class C extends B {
}
It compiles just fine.
2 I do not insist on compiling such somewhat strange cases. If they can not be translated to a readable code in C++, then fine, the backend will just fail with an error message. In fact, I am more interested in a general way of resolving the circular dependencies like that in C++.
EDIT 2
Thank you all, I am impressed by the efficiency of this site.
I concluded that, because:
- the header files generated are going to be used by other programmers;
- guessing from your answers, there is likely no solution that produces simple, readable header files;
- circular references involving return types are probably rare;
- I avoid C++ because, amongst others, it allows for solutions like that -- I know C++ has its uses, but personally, I prefer languages that have a simpler grammar, like Java;
the backend will:
- use forward declarations where possible;
- otherwise it will use includes, checking if the latter is circular; if yes, it will fail with an error message.
Cheers, Artur