Pass pointer to pthread of class member declared as friend - c++

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.

Related

Friend member function without class declaration

There is probably a really easy fix for this but it's boggling me currently. So, I'm writing C++ classes to the effect of:
Header.h:
#pragma once
//...
class arrayObj
{
private:
// some variables...
public:
//constructor, destructor, getters, etc...
friend void objManager::foo();
};
//...
class objManager
{
private:
//...
std::vector<std::shared_ptr<arrayObj>> array;
public:
void foo();
//other methods...
};
Now, as-is, my compiler will not find the class declaration of objManager (or the member function) declared for the friend inclusion. However, with the objManager declaration placed prior to the arrayObj, the arrayObj is no longer declared for the internal vector of shared pointers. Is there any way to forward declare objManager in this instance or otherwise solve this issue without dismantling the objManager into separate classes?
You need to forward-declare arrayObj, then put the full definition of the objManager, and then finally the definition of arrayObj:
class arrayObj;
class objManager {
std::vector<std::shared_ptr<arrayObj>> array; // OK, fwd-declare is fine for this
public:
void foo();
// etc.
};
class arrayObj {
public:
friend void objManager::foo();
// etc.
};
In order to declare a friend, that method has to already have been seen, so it has to go first. The forward declaration is a consequence of the vector.

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

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 );

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).

In C++ how to inherit a parent class' non-member functions, which is simply defined in the file?

I have codes like this:
class A{ // declaration is simplified
virtual void FNC1();
};
bool compare(S s1,S s2){
return s1<s2;
}
void A::FNC1(){
iterator it;
sort(it.begin(),it.end(),compare);
}
class B : public A{
virtual void FNC1();
};
void B:FNC1(){
iterator it;
// do something different
sort(it.begin(),it.end(),compare);
}
So I used class B to inherit class A and overrode the function FNC1(), but the problem is, as in the std::sort() function, the 3rd variable should really be a function, and such function is always directly declared. I really want to know what to do to avoid the copy and paste and make B directly inherit this function. I have tried to put the compare() function as a member function of A, and it won't compile:
sort(it.begin(), it.end(), this->compare);
I tried to include the compare function into a separate header file, and it says I cannot declare it. How could I correctly make B inherits this function? Because, in practical, I have 3 classes all need to reuse A's codes and the compare function is really a complicated one.
Your problem is that function compare is defined in the header, meaning that you have its body there in addition to its signature. If you include the header in two places, the compiler will complain about multiple definitions. You should only have the declaration in the header, and the definition in a .cpp file.
This should go into A's header, let's call it a.h
bool compare(S s1,S s2);
This should go into a.cpp
bool compare(S s1,S s2){
return s1<s2;
}
By the way, just to clear up the terminology, you cannot inherit a non-member function. You can use any non-member function anywhere, as long as you include its declaration and link against its object file.
You could make the compare function a static member function of the base class, rather than making it free-standing:
class A{ // declaration is simplified
virtual void FNC1();
public:
static bool compare(const A& s1, const A& s2) {
return ...; // The logic behind your compare function goes here
}
};
You can use the function like this:
sort(it.begin(), it.end(), A::compare);
You are on the right track. You can simply reuse the compare function, you don't need to modify it or try to "inherit" it or any such thing.
The following should compile and run without error.
#include <algorithm>
#include <vector>
struct S { int i; };
class A{ // declaration is simplified
public:
virtual void FNC1();
};
bool compare(const S& s1,const S& s2){
return s1.i < s2.i;
}
void A::FNC1(){
std::vector<S> v;
std::sort(v.begin(),v.end(),compare);
}
class B : public A{
public:
virtual void FNC1();
};
void B::FNC1(){
std::vector<S> v;
// do something different
std::sort(v.begin(),v.end(),compare);
}
int main () { A a; B b; a.FNC1(); b.FNC1(); }
The reason it won't compile if you make compare a member of A is probably that you are not making it public or protected. By default, members of a class are private, and a private member cannot be seen by a derived class.
You need:
class A{ // declaration is simplified
{
virtual void FNC1();
protected:
bool compare( S s1, S s2 ){...}
};

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.