Solved

forward-declare class B as being derived from class A

Posted on 2002-04-19
13
330 Views
Last Modified: 2011-08-18
I want to do something, like:
 class B : public A;
That is: I want to forward-declare Type B, but
let the compiler know, that B is derived from A.
However, the Compiler (or even C++-spec)
doesn't seem to accept this.

The reason, I'd need it is:
  In some part of my prog, I'm using only
  pointers to these classes, and I want to pass
  a B* to a method that takes a  const A*  
  (without casting, and without #include'ing
  the real definition of B)
Sounds not too far off, does it ?

The Compiler I need it for (if that should make
 a difference) is SUN's Forte WS6U2.

This question is quite important to me, therefore
I won't accept simple "won't go"-answers unless
they also point out, *why* this would be impossible or
what trouble this would inevitably put me into.
0
Comment
Question by:avl
  • 4
  • 4
  • 2
  • +2
13 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 6953597
>>forward-declare class B as being derived from class A

That's not possible. (If you need a "why", consult your compiler error message :o)

But what you want to do is not uncommon - use interfaces to accomplish that:

#define interface struct

interface IDemo {

virtual void Method1 ( int, int) = 0;
virtual void Method2 ( ) = 0;
};

class CDemo: public IDemo {

CDemo () {}
~CDemo () {}

virtual void Method1 ( int, int) { /* ... */ };
virtual void Method2 ( )  { /* ... */ };

};

and pass a pointer to CDemo to functions that expect a IDemo* - that's the common way to do that...
0
 

Author Comment

by:avl
ID: 6953760
>>forward-declare class B as being derived from class A
>That's not possible. (If you need a "why", consult your
>compiler error message :o)

The compiler just told me a parse-error:  Not very
enlightening. (Do other Compilers give more informative
feedback ?)

In your example you actually *define* class CDemo,
which is not what I was after.

I wanted either an explanation, why my wish was
unfulfillable, or (if one exists) the syntax of how I can
make it work.

There is a bit more to the classes than I wrote in the
question:
The whole class-hierarchy is already setup, and cannot
be changed anymore. (Thus, I can't insert any "dummy"
classes).
Actually, my goal was to avoid #include'ing the class-
header-files into some of the cpp-files, to reduce the
number of dependencies.
0
 
LVL 86

Expert Comment

by:jkr
ID: 6953797
>>In your example you actually *define* class CDemo

Well, at some point, you do need a declaration/implementation.

You'd use it like

void SomeFunc ( IDemo* p);

CDemo cd;

SomeFunc ( &cd);
0
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 

Author Comment

by:avl
ID: 6953940
No, without passing through the definition of CDemo,
 (which is, say, defined in cdemo.hpp, which again
  includes  idemo.hpp and lots of other necessary(!)
  stuff, that all in all results in a slow compile)
the C++-compiler would even barf on:
   void SomeFunc ( const IDemo* p);
   CDemo* someOtherFunc();
   CDemo *cd = someOtherFunc();
   SomeFunc (cd);  <-- no matching function found.
because then the compiler doesn't know, that
CDemo is a SubClass of  IDemo.

If it were not for the relationship between
 IDemo and CDemo, I would be all fine, just
 forward-declaring CDemo and IDemo.
E.g..: If SomeProc() were declared with a CDemo* or
 if my local pointer variable was a IDemo, I would not
 need to include cdemo.hpp.

I don't want to include cdemo.hpp, but still let the
compiler know, that CDemo is a SubClass of IDemo.
("cdemo.hpp" is still included into other cpp-files, e.g.:
where someFunc(),someOtherFunc(),... are implemented.)

Is my problem clear now ?
0
 
LVL 30

Expert Comment

by:Axter
ID: 6954209
>>Is my problem clear now ?
Not really.  :-)

If class 'B' derives from class 'A', then in order to compile class 'B' you have to include the declaration for class 'A'.
And in order to compile any implementation that is using class 'B', you would have to include the declaration for class 'A'.

I'm not sure if that's what you're trying to do, but if so, there's no way around that.  The compiler needs access to the base class declaration in order to compile a derive class implementation.
0
 
LVL 86

Expert Comment

by:jkr
ID: 6954222
>>The compiler needs access to the base class declaration

Yup - that's why I suggested an interface...
0
 

Author Comment

by:avl
ID: 6954279
No,  but we're coming nearer, hopefully  :-)

First of all, I'm not a C++ newbie.  I know certainly well,
when I really need a fully defined class, and where an
incompletely defined (== forward-declared) class
suffices.

It is clear, that when I really use the internals (methods,...) of class B (the derived one), I absolutely undoubtedly
need fully declared class B and A.

I'm talking about a piece of code, that may be the content
of a single cpp-file, which does NOT use the internals
of neither A nor B, but only passes around pointers to
these classes.

passing around pointers is usually something, where
forward-declared classes fully suffice.

BUT, I also want to cast pointers.  And for this I'd
need to tell the compiler somehow the following:
"I don't care, what class A and class B really look
like, but B will be declared somewhere else as being
derived from A, so a pointer to B should be implicitly
cast-able to a pointer to A, as it would, if you knew
the internals of these classes now."

I just want to tell the compiler that pointers to
B are one-way-compatible to pointers to A.

I've experienced already, that my first attempt
(class B : class A;  <-- attempted forward declaration
of B with little extra information) failed with a parse-error,
thus very likely is not valid C++ for now.

And now I'm out for insight on why this has not been
recognized as useful and added to C++-language,
or some other way, to make A* and B* compatible,
but not including the complete declaration of
them, and neither doing fake-declaration of B.
(A would even be available in my case)
0
 
LVL 86

Expert Comment

by:jkr
ID: 6954298
Well, that is something (if I am still with you :o) that can be done using a 'dynamic_cast()' - however, in order for this to work, the compiler needs to have 'seen' the declaration at some time.

What you could always do is uind C-style casts...
0
 
LVL 30

Expert Comment

by:Axter
ID: 6955116
>>And now I'm out for insight on why this has not been
>>recognized as useful and added to C++-language,
You can accomplish this in C++.  It's called a proxy class.
A proxy class will allow you to use a class without having to have access to the target class header.

That is the only way you're going to be able to hide the base class header class.

It really makes no sense to tell an implementation that B is derived from A, without telling it what A looks like.
Even if you could magically get the compiler to see B as derived from A (without declaration), the compiler wouldn't be able to put that information to any use,
 since the compliler wouldn't know what data type 'A' has, or what member functions 'A' has.
What use would that be?


Since this type of code would be ambiguous, it would not be added to the C++ language.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 6958402
First, it sounds like the only reason you want to do all of this is to avoid having the compiler read a particular header file.  If so, you must have a very slow compiler, or one that does not implement precompiled headers.  Get some good tools.

But more importantly, the question makes no sense.  The reason you might need to know that B is derived from A is that at some point you plan on doing something like:

     m_pcB->DoThatFnThatsInBbutNotInA(TRUE);

And the only way you could even think of doing that is if the class B had been defined somewhere.

Otherwise, if you are only going to use members of A, then why not just declare it as a pointer-to-class-A?  This is very common.  For instance, a function expects a CDialog* but a CWnd* can easily be passed around until such time as you need to use the specialized members of CDialog.  At that time you just cast it to the derived class.

If I missunderstand, then please post a few lines of code that illustrate and example of what you are trying to do and why it is not working.

-- Dan
0
 
LVL 22

Accepted Solution

by:
ambience earned 300 total points
ID: 6959217
>> BUT, I also want to cast pointers.  And for this I'd
need to tell the compiler somehow the following:
"I don't care, what class A and class B really look
like, but B will be declared somewhere else as being
derived from A, so a pointer to B should be implicitly
cast-able to a pointer to A, as it would, if you knew
the internals of these classes now."

so much already said, you may not care what A and B are , and that you may know B derives from A, so it can be "implicitly casted to pointer to A". But you see that compiler doesnt know that.

And what you call IMPLICIT casting , on part of the compiler is infact some arithmetic that depends upons the layout of both A and B. The compiler has to deal with the memory layout of B so that to be able to cast that to A.

possibly the compiler adds an "+/-offset" to the pointer to B and interprets the resulting value as a poointer to A.

And the value of that offset depends upon the internals of A i.e. members and aggregates inside A or B affect the offset. And things get real complicated with virtual inheritence.

If this doesnt make sense , think about the case of multiple inheritence. And that is why you need the declaration of both A and B, at the time of implicit conversions.

Hope this helps, correct me if i am wrong.

0
 
LVL 22

Expert Comment

by:ambience
ID: 6959238
>> And now I'm out for insight on why this has not been
recognized as useful and added to C++-language,

Do you still think so ?
0
 

Author Comment

by:avl
ID: 6959257
Now, that is the type of answer, what I had hoped for,
(even though a positive answer would have made me
happier.)

I didn't know, that such an implicit cast has that much magic
involved, but now that you wrote it, it is clear, why what I
wanted is principially unfulfillable.

Sorry for the others, who spent their time on this thread,
but only ambience hit the nail on its head.
0

Featured Post

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Move constructor only called if marked noexcept? 6 104
C++ question 3 65
c++ syntax question 9 48
Embarcadero C++ builder XE10.1 Berlin TRegistry declaration 1 27
When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question