C++03 Resolve a circle composition when calling a member function - c++

I've got the following class structure. This obviously won't compile. I can forward declare B. Then, I can either use function pointers in function calls but it's not a nice solution, as I would call other other functions in A from A::funcA or put part of the declaration of B into a header, which would be a few hundreds of lines and would be practical.
What (else) would be the preferred way to handle this situation?
class B;
class A
{
public:
void funcA(B* b);
double funcA2();
int funcA4(B* b);
private:
E memberA1;
E memberA2;
};
void A::funcA( B* b) {
b->funcB(a->memberA1, a->memberA2);
class B : public BBase
{
public:
void FuncB(E* e1, E* e2)
{
/* using const objects of B that are initialized
by B() and some other functions... */
}
std::vector<C*> memberB1; // C has std::vector<A*> memberC1
};
int main() {
calling B->memberB1.at(0)->memberC1.at(0)->funcA();
}
I have the the following (omitting some unneccesary lines):
A.h
Class B;
Class A {
declaration of A
};
A.cpp ....
B.h
#include "A.h"
#include "BBase.h"
Class B {
declaration of B
};
B.cpp ....
BBase.h
#include "C.h"
#include "A.h"
#include "AInterface.h"
typedef std::vector<AInterface> AList;
BBase {
declaration of abstract BBase
};
BBase.cpp ....`
But I still get error: member access into incomplete type 'B'.

Assuming E and C are adequately declared/defined, then what you have is almost fine. The problem is that you define the member function of A before you have the definition of the B class, make sure that class B is fully defined (the actual class, not the full implementation of its member functions) before you you have the A member functions implemented.
So something like this:
class B;
class A { ...; void member_function(B*); ... };
class B { ...; void other_member_function(); ... };
void A::member_function(B* b) { ...; b->other_member_function(); ... }

I would suggest to use either the Interface instead of concrete B class
class B : public IB{
};
and pass IB instead of B to A.
either even better in c++ use a template function and bind your member function which you want to call
a.funcA( std::bind( &B::funcB, &b, someArg );

Related

Forward declaration of a class alone errors out regarding class not recognized [duplicate]

I know that I can do:
class Foo;
but can I forward declare a class as inheriting from another, like:
class Bar {};
class Foo: public Bar;
An example use case would be co-variant reference return types.
// somewhere.h
class RA {}
class RB : public RA {}
... and then in another header that doesn't include somewhere.h
// other.h
class RA;
class A {
public:
virtual RA* Foo(); // this only needs the forward deceleration
}
class RB : public RA; // invalid but...
class B {
public:
virtual RB* Foo(); //
}
The only information the compiler should need to process the declaration of RB* B:Foo() is that RB has RA as a public base class. Now clearly you would need somewhere.h if you intend to do any sort of dereferencing of the return values from Foo. However, if some clients never calls Foo, then there is no reason for them to include somewhere.h which might significantly speed compilation.
A forward declaration is only really useful for telling the compiler that a class with that name does exist and will be declared and defined elsewhere. You can't use it in any case where the compiler needs contextual information about the class, nor is it of any use to the compiler to tell it only a little bit about the class. (Generally, you can only use the forward declaration when referring to that class without other context, e.g. as a parameter or return value.)
Thus, you can't forward declare Bar in any scenario where you then use it to help declare Foo, and it flat-out doesn't make sense to have a forward declaration that includes the base class -- what does that tell you besides nothing?
Forward declarations are declarations, not definitions. So, anything that requires the declaration of a class (like pointers to that class) need only the forward declaration. However, anything that would require the definition - i.e. would need to know the actual structure of the class - would not work with just the forward declaration.
Derived classes definitely need to know the structure of their parent, not just that the parent exists, so a forward declaration would be insufficient.
No it is not possible to forward declare inheritance, even if you are only dealing with pointers. When dealing with conversions between pointers, sometimes the compiler has to know the details of the class to do the conversion correctly. This is the case with multiple inheritance. (You could special case some parts parts of the hierarchy that only use single inheritance, but that isn't part of the language.)
Consider the following trivial case:
#include <stdio.h>
class A { int x; };
class B { int y; };
class C: public A, public B { int z; };
void main()
{
C c; A *pa = &c; B *pb = &c; C *pc = &c;
printf("A: %p, B: %p, C: %p\n", pa, pb, pc);
}
The output I received (using 32 bit visual studio 2010), is:
A: 0018F748, B: 0018F74C, C: 0018F748
So for multiple inheritance, when converting between related pointers, the compiler has to insert some pointer arithmetic to get the conversions right.
This is why, even if you are dealing only with pointers, you can't forward declare inheritance.
As for why it would be useful, it would improve compile times when you do want to make use of co-variant return types instead of using casts. For example this will not compile:
class RA;
class A { public: virtual RA *fooRet(); };
class RB;
class B : public A { public: virtual RB *fooRet(); };
But this will:
class RA;
class A { public: virtual RA *fooRet(); };
class RA { int x; };
class RB : public RA{ int y; };
class B : public A { public: virtual RB *fooRet(); };
This is useful when you have objects of type B (not pointers or references). In this case the compiler is smart enough to use a direct function call, and you can use the return type of RB* directly without casting. In this case, usually I go ahead and make the return type RA * and do a static cast on the return value.
All you needed to do was declare RB without the : public RA (oh, and also add ; to the end of your class definitions):
class RA;
class A {
public:
virtual RA* Foo();
};
class RB;
class B {
public:
virtual RB* Foo();
};
// client includes somewhere.h
class RA {};
class RB : public RA {};
int main ()
{
return 0;
}
However, this doesn't solve the specific problem described nicely in the answer by user1332054.
Some of the other answers appear to show some misconceptions that I'd like to dispel:
Forward declaring is useful even when when we know that the definition is not likely to be included. This allows us to do a lot of type-deduction in our libraries that make them compatible with many other established libraries without including them. Including libraries unnecessarily leads to too many nested includes that can explode the compile time. It's good practice to make your code compatible when appropriate, and to include as little as possible.
Typically you can define a class with pointers to classes that have only been declared and not defined. Example:
struct B;
struct A
{
B * b_;
B * foo ()
{
return b_;
}
B & foo (B * b)
{
return *b;
}
};
int main ()
{
return 0;
}
The above compiles fine, because the compiler doesn't need to know anything about B.
An example where it might be a bit harder to realise that the compiler needs more information:
struct B;
struct A
{
B * foo ()
{
return new B;
}
};
The above problem is because new B invokes the B::B() constructor which hasn't been defined yet. Also:
struct B;
struct A
{
void foo (B b) {}
};
Here foo must call the copy constructor for b, which also hasn't been defined yet. Lastly:
struct B;
struct A
{
B b;
};
Here we have implicitly defined A with the default constructor, which calls the default constructor of call its members,b, which hasn't been defined yet. I think' you get the point.
So, in reference to the more general problem, described by user1332054, I honestly don't understand why it's not possible to use pointers to undefined classed in an inherited virtual function.
More broadly though, I think that you're making it more difficult for yourself by defining your classes instead of only declaring them. Here's an example where you get to DoCleverStuff with your classes in your library before you've defined any of your classes at all:
// Just declare
class RA;
class RB;
class A;
class B;
// We'll need some type_traits, so we'll define them:
template <class T>
struct is_type_A
{
static constexpr bool value = false;
};
template <>
struct is_type_A <A>
{
static constexpr bool value = true;
};
template <class T>
struct is_type_B
{
static constexpr bool value = false;
};
template <>
struct is_type_B <B>
{
static constexpr bool value = true;
};
#include <type_traits>
// With forward declarations, templates and type_traits now we don't
// need the class definitions to prepare useful code:
template<class T>
typename std::enable_if<is_type_A<T>::value, RA *>::type
DoCleverStuff (T & t)
{
// specific to A
return t.fooRet();
}
template<class T>
typename std::enable_if<is_type_B<T>::value, RB *>::type
DoCleverStuff (T & t)
{
// specific to B
return t.fooRet();
}
// At some point the user *does* the include:
class RA
{
int x;
};
class RB : public RA
{
int y;
};
class A
{
public:
virtual RA * fooRet()
{
return new RA;
}
};
class B : public A
{
public:
virtual RB * fooRet()
{
return new RB;
}
};
int main ()
{
// example calls:
A a;
RA * ra = DoCleverStuff(a);
B b;
RB * rb = DoCleverStuff(b);
delete ra;
delete rb;
return 0;
}
I don't think it's useful. Consider: you have defined a class, Bar:
class Bar {
public:
void frob();
};
Now you declare a class Foo:
class Foo;
All you can do with Foo is construct a pointer to it. Now, suppose you add the information that Foo is derived from Bar:
class Foo: public Bar;
What can you now do that you couldn't do before? I think that all you can do is accept a pointer to Foo and cast it into a pointer to Bar, then use that pointer.
void frob(Foo* f) {
Bar *b = (Bar)f;
b->frob();
}
However, you must have generated the pointer elsewhere, so you could have just accepted a pointer to Bar instead.
void frob(Bar* b) {
b->frob();
}

Inheritance of template class [duplicate]

I know that I can do:
class Foo;
but can I forward declare a class as inheriting from another, like:
class Bar {};
class Foo: public Bar;
An example use case would be co-variant reference return types.
// somewhere.h
class RA {}
class RB : public RA {}
... and then in another header that doesn't include somewhere.h
// other.h
class RA;
class A {
public:
virtual RA* Foo(); // this only needs the forward deceleration
}
class RB : public RA; // invalid but...
class B {
public:
virtual RB* Foo(); //
}
The only information the compiler should need to process the declaration of RB* B:Foo() is that RB has RA as a public base class. Now clearly you would need somewhere.h if you intend to do any sort of dereferencing of the return values from Foo. However, if some clients never calls Foo, then there is no reason for them to include somewhere.h which might significantly speed compilation.
A forward declaration is only really useful for telling the compiler that a class with that name does exist and will be declared and defined elsewhere. You can't use it in any case where the compiler needs contextual information about the class, nor is it of any use to the compiler to tell it only a little bit about the class. (Generally, you can only use the forward declaration when referring to that class without other context, e.g. as a parameter or return value.)
Thus, you can't forward declare Bar in any scenario where you then use it to help declare Foo, and it flat-out doesn't make sense to have a forward declaration that includes the base class -- what does that tell you besides nothing?
Forward declarations are declarations, not definitions. So, anything that requires the declaration of a class (like pointers to that class) need only the forward declaration. However, anything that would require the definition - i.e. would need to know the actual structure of the class - would not work with just the forward declaration.
Derived classes definitely need to know the structure of their parent, not just that the parent exists, so a forward declaration would be insufficient.
No it is not possible to forward declare inheritance, even if you are only dealing with pointers. When dealing with conversions between pointers, sometimes the compiler has to know the details of the class to do the conversion correctly. This is the case with multiple inheritance. (You could special case some parts parts of the hierarchy that only use single inheritance, but that isn't part of the language.)
Consider the following trivial case:
#include <stdio.h>
class A { int x; };
class B { int y; };
class C: public A, public B { int z; };
void main()
{
C c; A *pa = &c; B *pb = &c; C *pc = &c;
printf("A: %p, B: %p, C: %p\n", pa, pb, pc);
}
The output I received (using 32 bit visual studio 2010), is:
A: 0018F748, B: 0018F74C, C: 0018F748
So for multiple inheritance, when converting between related pointers, the compiler has to insert some pointer arithmetic to get the conversions right.
This is why, even if you are dealing only with pointers, you can't forward declare inheritance.
As for why it would be useful, it would improve compile times when you do want to make use of co-variant return types instead of using casts. For example this will not compile:
class RA;
class A { public: virtual RA *fooRet(); };
class RB;
class B : public A { public: virtual RB *fooRet(); };
But this will:
class RA;
class A { public: virtual RA *fooRet(); };
class RA { int x; };
class RB : public RA{ int y; };
class B : public A { public: virtual RB *fooRet(); };
This is useful when you have objects of type B (not pointers or references). In this case the compiler is smart enough to use a direct function call, and you can use the return type of RB* directly without casting. In this case, usually I go ahead and make the return type RA * and do a static cast on the return value.
All you needed to do was declare RB without the : public RA (oh, and also add ; to the end of your class definitions):
class RA;
class A {
public:
virtual RA* Foo();
};
class RB;
class B {
public:
virtual RB* Foo();
};
// client includes somewhere.h
class RA {};
class RB : public RA {};
int main ()
{
return 0;
}
However, this doesn't solve the specific problem described nicely in the answer by user1332054.
Some of the other answers appear to show some misconceptions that I'd like to dispel:
Forward declaring is useful even when when we know that the definition is not likely to be included. This allows us to do a lot of type-deduction in our libraries that make them compatible with many other established libraries without including them. Including libraries unnecessarily leads to too many nested includes that can explode the compile time. It's good practice to make your code compatible when appropriate, and to include as little as possible.
Typically you can define a class with pointers to classes that have only been declared and not defined. Example:
struct B;
struct A
{
B * b_;
B * foo ()
{
return b_;
}
B & foo (B * b)
{
return *b;
}
};
int main ()
{
return 0;
}
The above compiles fine, because the compiler doesn't need to know anything about B.
An example where it might be a bit harder to realise that the compiler needs more information:
struct B;
struct A
{
B * foo ()
{
return new B;
}
};
The above problem is because new B invokes the B::B() constructor which hasn't been defined yet. Also:
struct B;
struct A
{
void foo (B b) {}
};
Here foo must call the copy constructor for b, which also hasn't been defined yet. Lastly:
struct B;
struct A
{
B b;
};
Here we have implicitly defined A with the default constructor, which calls the default constructor of call its members,b, which hasn't been defined yet. I think' you get the point.
So, in reference to the more general problem, described by user1332054, I honestly don't understand why it's not possible to use pointers to undefined classed in an inherited virtual function.
More broadly though, I think that you're making it more difficult for yourself by defining your classes instead of only declaring them. Here's an example where you get to DoCleverStuff with your classes in your library before you've defined any of your classes at all:
// Just declare
class RA;
class RB;
class A;
class B;
// We'll need some type_traits, so we'll define them:
template <class T>
struct is_type_A
{
static constexpr bool value = false;
};
template <>
struct is_type_A <A>
{
static constexpr bool value = true;
};
template <class T>
struct is_type_B
{
static constexpr bool value = false;
};
template <>
struct is_type_B <B>
{
static constexpr bool value = true;
};
#include <type_traits>
// With forward declarations, templates and type_traits now we don't
// need the class definitions to prepare useful code:
template<class T>
typename std::enable_if<is_type_A<T>::value, RA *>::type
DoCleverStuff (T & t)
{
// specific to A
return t.fooRet();
}
template<class T>
typename std::enable_if<is_type_B<T>::value, RB *>::type
DoCleverStuff (T & t)
{
// specific to B
return t.fooRet();
}
// At some point the user *does* the include:
class RA
{
int x;
};
class RB : public RA
{
int y;
};
class A
{
public:
virtual RA * fooRet()
{
return new RA;
}
};
class B : public A
{
public:
virtual RB * fooRet()
{
return new RB;
}
};
int main ()
{
// example calls:
A a;
RA * ra = DoCleverStuff(a);
B b;
RB * rb = DoCleverStuff(b);
delete ra;
delete rb;
return 0;
}
I don't think it's useful. Consider: you have defined a class, Bar:
class Bar {
public:
void frob();
};
Now you declare a class Foo:
class Foo;
All you can do with Foo is construct a pointer to it. Now, suppose you add the information that Foo is derived from Bar:
class Foo: public Bar;
What can you now do that you couldn't do before? I think that all you can do is accept a pointer to Foo and cast it into a pointer to Bar, then use that pointer.
void frob(Foo* f) {
Bar *b = (Bar)f;
b->frob();
}
However, you must have generated the pointer elsewhere, so you could have just accepted a pointer to Bar instead.
void frob(Bar* b) {
b->frob();
}

How to declare friend method when class definitions cross reference?

I want to define two classes, A and B. A has a data member which is a Class B object and is in-class initialised. A also has a method to retrieve the value in this B type data member and this method would be declared as a friend method in B. Here is my code:
class A{
public:
int getBValue();
private:
B b=B(1);
};
class B{
public:
friend int A::getBValue();
B(int i):value(i){}
private:
int value;
};
int A::getBValue(){
return b.value;
}
And unsurprisingly the compilation had failed because of unknown type B in class A definition. I had tried to swap the definitions of A and B in the source and the result was even worse. Is there a possible way to resolve this cross reference issue between A and B?
If this is the complete code as you have it, then the problem is that the compiler doesn't know what a B is at the time it is compiling class A. One way to solve it is by creating a pointer to B instead of having a B itself:
A.h
#ifndef CLASS_A
#define CLASS_A
class B;
class A{
public:
int getBValue();
private:
B *b;
};
#endif
B.h
#ifndef CLASS_B
#define CLASS_B
#include "A.h"
class B{
public:
friend int A::getBValue();
B(int i):value(i){}
private:
int value;
};
#endif
A.cpp
#include "A.h"
#include "B.h"
int A::getBValue(){
return b->value;
}
Replacing an embedded member of type B with a pointer (or reference) to a B changes the way your class works and needs additional care when copying objects of class A.
When you reverse the definitions, you cannot make a member function of class A a friend of class B, because the type of A is incomplete at the time of the friend declaration. But you can make the entire class A a friend.
A solution with class A having an embedded member of class B could look like this:
class A;
class B{
public:
friend class A;
B(int i):value(i){}
private:
int value;
};
class A{
public:
int getBValue();
private:
B b=B(1);
};
int A::getBValue(){
return b.value;
}
Changes made:
Declared B before A. A forward declaration for A is used.
Made the class A a friend of B. This works even when A is not yet fully defined.
Compiles with g++ version 4.7.2 (-std=c++11 needed for B b=B(1);)
Anyway, having a member of class A accessing a private member of class B is something which can (and should) almost always be avoided (see Laszlo Papp's comment on your post).

friend declaration block an external function access to the private section of a class

I'm trying to force function caller from a specific class.
For example this code bellow demonstrate my problem.
I want to make 'use' function would be called only from class A.
I'm using a global namespace all over the project.
a.h
#include "b.h"
namespace GLOBAL{
class A{
public:
void doSomething(B);
}
}
a.cpp
#include "a.h"
using namespace GLOBAL;
void A::doSomething(B b){
b.use();
}
b.h
namespace GLOBAL{
class B{
public:
friend void GLOBAL::A::doSomething(B);
private:
void use();
}
Compiler says:
‘GLOBAL::A’ has not been declared
‘void GLOBAL::B::use()’ is private
Can anyone help here ?
Thanks a lot,
Mike.
This is because in the friend delcaration you are refering to a member of a class.
For this to work the compiler must already have seen the full definition of A.
a.h
// #include "b.h" // remove this line it is not needed.
namespace GLOBAL{
class B; // Forward declare the class here.
class A{
public:
void doSomething(B&); // Note: This should probably be a reference.
// Change to doSomething(B&);
}
}
b.h
// Add this line it is needed for the friend declaration.
// To have a member as a friend we need the definition of 'A'
#include "a.h"
namespace GLOBAL{
class B{
public:
friend void GLOBAL::A::doSomething(B&);
private:
void use();
}
a.cpp
#include "a.h"
// Add this line to include the B definition so you know how to call use()
#include "b.h"
using namespace GLOBAL;
void A::doSomething(B& b){ // b should be a reference otherwise you are copying it.
b.use();
}
The following compiles fine from a cpp file:
namespace GLOBAL
{
class B;
class A
{
public:
void doSomething(B& b);
};
};
namespace GLOBAL
{
class B
{
public:
friend void GLOBAL::A::doSomething(B&);
private:
void use()
{
}
};
};
void GLOBAL::A::doSomething(B& b)
{
b.use();
}
As best I can tell your problem arises from the fact that you include "b.h" from "a.h" that defines the B class before the A class is defined yet the B class makes a reference to the A class. So you have problems. However you can't forward declare an object of type B because you are copying via the stack. Hence why I use a reference to class B (as this doesn't require the B object to be known in advance).
Basically you have some fundamental problems with your structure that needs working out. You need to do some reading up on forward declarations and circular dependencies
Edit: Specifying purely that class A is a friend of B (rather than a specific function in A that references B) is actually a possibility as the friend definition provides a kind of forward declaration. As such the following code compiles:
namespace GLOBAL
{
class B
{
public:
friend class A;
private:
void use()
{
}
};
};
namespace GLOBAL
{
class A
{
public:
void doSomething(B b);
};
};
void GLOBAL::A::doSomething(B b)
{
b.use();
}
As such in your code, originally posted, chaging the friend statement to, simply
friend class A;
should allow your code to compile.
Move #include "b.h" from a.h to a.cpp after the first #include directive. The compiler doesn't need to see the friend declaration until it's compiling the function that the declaration applies to.

Pass pointer to pthread of class member declared as friend

I have a class called BaseB which can be called from A.
I need to have class A pass a pointer to pthread_create of a member function in class BaseB that also happens to be declared as:
friend void ThreadedTask(BaseB* b);
in Class BaseB's header under public accessibility. However, in the actual cpp file it is not declared as a member of that class with the class scope. Instead, it is declared as
void ThreadedTask(BaseB* b) { .... }
So how can I tell the pthread_create to use the friended class member?
I read the C++ FAQ in Section 33 and it says:
Because a member function is meaningless without an object to invoke
it on, you can't do this directly (if The X Window System was
rewritten in C++, it would probably pass references to objects around,
not just pointers to functions; naturally the objects would embody the
required function and probably a whole lot more).
??
If I understand your situation correctly, you have something like the following:
/*** baseb.hpp ***/
class BaseB {
friend void ThreadedTask(BaseB* b);
public:
// ...
};
/*** baseb.cpp ***/
#include "baseb.hpp"
void ThreadedTask(BaseB* b) {
// impl
}
// other BaseB definitions
/*** a.hpp ***/
struct A {
void somefunc();
};
/*** a.cpp ***/
#include "a.hpp"
#include "baseb.hpp"
struct A {
void somefunc() {
// pass ThreadedTask to pthread_create
// but where is ThreadedTask declared?
}
};
What's missing is a visible declaration for ThreadedTask.
Either make the declaration visible in baseb.hpp, since it's now effectively a public implementation detail of BaseB anyway:
/*** baseb.hpp ***/
class BaseB;
void ThreadedTask(BaseB* b);
class BaseB {
friend void ThreadedTask(BaseB* b);
public:
// ...
};
Or have A declare it on its own, so the declaration can remain "hidden":
/*** a.cpp ***/
#include "a.hpp"
#include "baseb.hpp"
void ThreadedTask(BaseB* b);
struct A {
void somefunc() {
// pass ThreadedTask to pthread_create
}
};
You will either have to declare ThreadedTask outside class declaration in BaseB.hpp, or cheat and declare it in the right namespace in A.cpp.