Partial classes

A

Adrian Hawryluk

Can one define a partial class (first part containing constants like
enums) and then define the rest of the class elsewhere?

I ask this because I've had in the past needed to defined two classes
(call them A and B), each dependent upon the other. Class A requires
the enum type defined in Class B. An example follows:

<header file="A.h">
#if !defined A_H
# define A_H

// Stub for forward referencing
class A;

# include “B.h”

class A
{
// Interface functions
void f(B* b, B::b_e enums);
...
};
#endif
</header>

<header file="B.h">
#if !defined B_H
# define B_H

// Stub for forward referencing
class B;

# include “A.h”
class B
{
public:
enum b_e { enum1, enum2 };

// Interface functions
...
};
#endif
</header>

The only way I see around this are:
1. Declare a public base class for B that contains the enums. It is not
dependent on A so no problem occurs. It would be declared with the
class B stub;
2. Declare the enums outside of class scope, removing the dependency
lock. It would be declared with the class B stub;
3. Make a faux template class, making the class a stub. Haven't tried
this.

Problems for each are:
1. Base classes would have a explicit size of 1, adding a small amount
of overhead.
2. Enum is not scoped to a class.
3. A bit overkill if it does work.

Any thoughts?


Adrian

--
========================================================
Adrian Hawryluk BSc. Computer Science
--------------------------------------------------------
Specialising in: OOD Methodologies in UML
OOP Methodologies in C, C++ and more
RT Embedded Programming
__------------------------------------------------__
-----[blog: http://adrians-musings.blogspot.com/]-----
'------------------------------------------------------'
This content is licensed under the Creative Commons
Attribution-Noncommercial-Share Alike 3.0 License
http://creativecommons.org/licenses/by-nc-sa/3.0/
=========================================================
 
V

Victor Bazarov

Adrian said:
Can one define a partial class (first part containing constants like
enums) and then define the rest of the class elsewhere?
No.


I ask this because I've had in the past needed to defined two classes
(call them A and B), each dependent upon the other. Class A requires
the enum type defined in Class B. An example follows:

<header file="A.h">
#if !defined A_H
# define A_H

// Stub for forward referencing
class A;

# include “B.h”

class A
{
// Interface functions
void f(B* b, B::b_e enums);
...
};
#endif
</header>

<header file="B.h">
#if !defined B_H
# define B_H

// Stub for forward referencing
class B;

# include “A.h”
class B
{
public:
enum b_e { enum1, enum2 };

// Interface functions
...
};
#endif
</header>

The only way I see around this are:
1. Declare a public base class for B that contains the enums. It is
not dependent on A so no problem occurs. It would be declared
with the class B stub;

That's the best solution, IMO.
2. Declare the enums outside of class scope, removing the dependency
lock. It would be declared with the class B stub;
3. Make a faux template class, making the class a stub. Haven't tried
this.

No sure what you mean here.
Problems for each are:
1. Base classes would have a explicit size of 1, adding a small amount
of overhead.

Not to the class inheriting from it.

class Base {};
class Derived : public Base { int a; };
#include <iostream>
int main() {
std::cout << "sizeof(Base) = " << sizeof(Base) << std::endl;
std::cout << "sizeof(Base in Derived) = "
<< sizeof(Derived) - sizeof(int) << std::endl;
}
2. Enum is not scoped to a class.
3. A bit overkill if it does work.

Any thoughts?

Base class!

V
 
P

Phlip

Adrian said:
Can one define a partial class (first part containing constants like
enums) and then define the rest of the class elsewhere?

What's the real problem you need to solve; the problem that lead you to this
attempted solution?
Problems for each are:
1. Base classes would have a explicit size of 1, adding a small amount
of overhead.

Google "premature optimization". Always go for the cleanest design first,
regardless of optimization. It's easier to make beautiful code fast than
fast code beautiful.

And in this specific case, C++ can optimize that stub size away.
2. Enum is not scoped to a class.

So what? What's the worst thing that could happen if some plebe class gets
its dirty hands on that enum?
3. A bit overkill if it does work.

Faux template classes are where it's at. Declare the enum somewhere, and
template them into your target class.

In you unit tests, you can create different enums to test the template. (You
do _have_ unit tests, don't you?)
 
P

Piyo

BTW, your class B is not dependent on class
A at all. (A is dependent on B though) based on
this example code.
<header file="A.h">
#if !defined A_H
# define A_H

Remove these two lines. Not required.
B is not dependent on A.
// Stub for forward referencing
class A;

# include “B.h”

class A
{
// Interface functions
void f(B* b, B::b_e enums);
...
};
#endif
</header>

<header file="B.h">
#if !defined B_H
# define B_H
Remove these two lines also. B is already
included in A.h and is thus takes care of itself.
// Stub for forward referencing
class B;

B is not dependent on A so you can remove this too.
# include “A.h”

class B
{
public:
enum b_e { enum1, enum2 };

// Interface functions
...
};
#endif
</header>

Can you describe your problem or post actual code that
demonstrates your need for partial class declarations?
 
A

Adrian Hawryluk

Victor said:

Yeah, I figured as much.
>
> That's the best solution, IMO.

Hmmm.
> What's the real problem you need to solve; the problem that lead you
> to this attempted solution?

The problem has occurred many times now. I'm not a newbie to C++, I've
been programming in it for 10 years now. I was just wondering if
anybody had another idea.
> Google "premature optimization". Always go for the cleanest design
> first, regardless of optimization. It's easier to make beautiful code
> fast than fast code beautiful.
>
> And in this specific case, C++ can optimize that stub size away.

Yeah, I know. Trouble is, there are compilers that f*** it up slowing
down certain apps because of it. I'm not optimising prematurely, as
I've said, I've been doing this for years.
>
> So what? What's the worst thing that could happen if some plebe class
> gets its dirty hands on that enum?

Wrong, that is probably closer to the best case, the worst case is you
get a name clash. And don't tell me about namespaces, it is OT from my
original question. I just want to keep the enum in place where it is used.
>
> Faux template classes are where it's at. Declare the enum somewhere,
> and template them into your target class.

Oh yeah, this also exposes the code, not what I want.
> In you unit tests, you can create different enums to test the
> template. (You do _have_ unit tests, don't you?)

I didn't come here to be insulted, just ask a question. Lol.
> BTW, your class B is not dependent on class
> A at all. (A is dependent on B though) based on
> this example code.

Sorry, is this better?

<header file="A.h">
#if !defined A_H
# define A_H

// Stub for forward referencing
class A;

# include “B.h”

class A
{
// Interface functions
void f(B* b, B::b_e enums);
...
};
#endif
</header>

<header file="B.h">
#if !defined B_H
# define B_H

// Stub for forward referencing
class B;

# include “A.h”
class B
{
public:
enum b_e { enum1, enum2 };

void f(A* a); ///< here is the dependent
// Interface functions
...
};
#endif
> Can you describe your problem or post actual code that
> demonstrates your need for partial class declarations?

As for the actual example, it would be too long and have lots of extra
non-relevant stuff, but trust me it does occur and has occurred at other
times before that.

One case would be in a Mediator pattern when a mediator 'A' requires the
ids from a mediator 'B' to access B's objects indirectly through B.

If the base class is the only solution that can be thought up, then so
be it.


Adrian
--
==========================================================
Adrian Hawryluk BSc. Computer Science
----------------------------------------------------------
Specialising in: OOD Methodologies in UML
OOP Methodologies in C, C++ and more
RT Embedded Programming
__--------------------------------------------------__
----- [blog: http://adrians-musings.blogspot.com/] -----
'--------------------------------------------------------'
My newsgroup writings are licensed under the Creative
Commons Attribution-Noncommercial-Share Alike 3.0 License
http://creativecommons.org/licenses/by-nc-sa/3.0/
==========================================================
 
P

Piyo

Adrian said:
Sorry, is this better?
BTW still based on the example, only A is dependent
on B fully. B does not need a full include in the
header (in the .cpp yes but not the header). A forward
declaration of class A in B is sufficient in the header.
But I am sure you know this :)
<header file="A.h">
#if !defined A_H
# define A_H

// Stub for forward referencing
class A;

# include “B.h”

class A
{
// Interface functions
void f(B* b, B::b_e enums);
...
};
#endif
</header>

<header file="B.h">
#if !defined B_H
# define B_H

// Stub for forward referencing
class B;

# include “A.h”
class B
{
public:
enum b_e { enum1, enum2 };

void f(A* a); ///< here is the dependent
// Interface functions
...
};
#endif
</header>


As for the actual example, it would be too long and have lots of extra
non-relevant stuff, but trust me it does occur and has occurred at other
times before that.

I do understand that it does occur and based on your suggestions, I
would do:

1) Hopefully your compiler is smart to do empty base class optimization
to eliminate your overhead.
1. Base classes would have a explicit size of 1, adding a small amount
of overhead.

Check this for reference about the optimization:
http://www.cantrip.org/emptyopt.html

2) doing the base class thing also kind of implies to me that you may
opt to namespace your enumerated independent of both class A and class
B and you can even reintroduce the enumerated type back into class B
if that is even necessary.

HTH
 
A

Adrian Hawryluk

Piyo said:
Adrian Hawryluk wrote:
Sorry, is this better?
BTW still based on the example, only A is dependent
on B fully. B does not need a full include in the
header (in the .cpp yes but not the header). A forward
declaration of class A in B is sufficient in the header.
But I am sure you know this :)
>> [snip]

Thanks, I do. I do it this way for (primarily) auto dependency
generation. If I were to change something in B that may have to rely on
some information in A later, I don't want to have to fiddle around with
the header file, or do a clean build of the entire system when it is not
necessary. It is a template setup that I prefer. But thank you again
for pointing it out. :)
I do understand that it does occur and based on your suggestions, I
would do:

1) Hopefully your compiler is smart to do empty base class optimization
to eliminate your overhead.

Check this for reference about the optimization:
http://www.cantrip.org/emptyopt.html
Thanks.

2) doing the base class thing also kind of implies to me that you may
opt to namespace your enumerated independent of both class A and class
B and you can even reintroduce the enumerated type back into class B
if that is even necessary.

Putting the enum in the class is more for ownership reasons to state
loud and clear that the enum's primary purpose is for that class without
adding a new namespace to the system, while avoiding name clashing.


Adrian
--
==========================================================
Adrian Hawryluk BSc. Computer Science
----------------------------------------------------------
Specialising in: OOD Methodologies in UML
OOP Methodologies in C, C++ and more
RT Embedded Programming
__--------------------------------------------------__
----- [blog: http://adrians-musings.blogspot.com/] -----
'--------------------------------------------------------'
My newsgroup writings are licensed under the Creative
Commons Attribution-Noncommercial-Share Alike 3.0 License
http://creativecommons.org/licenses/by-nc-sa/3.0/
==========================================================
 
O

Old Wolf

Can one define a partial class (first part containing constants like
enums) and then define the rest of the class elsewhere?

#if !defined A_H
# define A_H

// Stub for forward referencing
class A;

# include "B.h"

This is not a recommended style; A.h should not both forward-declare
and define A. The forward declaration should be inside B.h . I assume
B.h requires A to be declared; what are you going to do if some other
unit includes B.h and not A.h ? Repeat the forward declaration in
every other unit?
class A
{
// Interface functions
void f(B* b, B::b_e enums);
...
};
#endif

The only way I see around this are:
2. Declare the enums outside of class scope, removing the dependency
lock. It would be declared with the class B stub;
Problems for each are:
2. Enum is not scoped to a class.

This isn't really much of a problem, to me. If you want to force
others to use B:: before the enum values and typename then you can
write B.h like this:

namespace B {
enum b_e { ....... };
};

class B {
..............
};

Then you have to use B::value for the enum values, even within B.cpp;
if you don't want this then you can include "using namespace B"
inside B.cpp .
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top