Solved

forward-declare class B as being derived from class A

Posted on 2002-04-19
13
328 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
 

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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

760 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

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now