avl
asked on
forward-declare class B as being derived from class A
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.
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.
ASKER
>>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.
>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.
>>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);
Well, at some point, you do need a declaration/implementation
You'd use it like
void SomeFunc ( IDemo* p);
CDemo cd;
SomeFunc ( &cd);
ASKER
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 ?
(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()
Is my problem clear now ?
>>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.
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.
>>The compiler needs access to the base class declaration
Yup - that's why I suggested an interface...
Yup - that's why I suggested an interface...
ASKER
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)
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)
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...
What you could always do is uind C-style casts...
>>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.
>>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.
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->DoThatFnThatsInBbut NotInA(TRU E);
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
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->DoThatFnThatsInBbut
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
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>> 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 ?
recognized as useful and added to C++-language,
Do you still think so ?
ASKER
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.
(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.
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...