friends of a class...

R

rory

Hi everyone. I'm trying to declare a function as a friend in one of my
classes. Correct me if I'm wrong but if I declare a friendly function
that means that I can access member of my class in that function? This
had been working for me with Borland C++ but once I changed to g++ I
get errors. Here's a brief example, I want to be able to access my
classes members from my friend function test():

#include <iostream>
using namespace std;

class myfirstclass
{
private:
public:
int number;
void greeting();
friend void test();
};

void test()
{
cout << myfirstclass->number;
}

void myfirstclass::greeting()
{
for(int i = 0; i<= number;i++)
{
cout<<number;
}
}

int main ()
{
myfirstclass myfirstobject;
myfirstobject.number =3;
myfirstobject.greeting();
return 0;
}

Any help is much appreciated,
Rory.
 
K

KasF

Hi,

your friend-function can't know your class ;-)
A friend-function can acces to the private Member of the class but it
must already know your class-OBJECT.

Your function must be defined like this:

friend void test(const myfirstclass& ob)
{
cout<<ob.number;
}
 
R

rory

Cheers. But then what's the point in declaring it as a friend? I could
just do this

class myfirstclass
{
private:
public:
int number;
void greeting();

};
void test(myfirstclass* test);

Isn't that the same thing? Actually perhaps I'm barking up the wrong
tree here. Let me know tell you more about why I thought the friend
keyword was the thing I needed. I need to call a function in my
application that starts a thread. The start thread function must be
passed a thread function that's declared as
uintptr_t csThread(void *clientData)
The thing is that I need this thread function to be able to access
members of my class yet I can't pass my class as a parameter given that
the start thread function has to be declared as above. I have this
application working and building using Borland's C++ and somehow it
works fine, I can access all the member of my class, but I'm porting
the application now and using g++ it gives errors. Obviously. Any ideas
on what I can do? I'd rather use the thread functions that are provided
by the API I am using rather than switching. Cheers,
Rory.
 
K

KasF

Which errors ??
Write them here please ;-)

A friend function isn't a good friend. You only need it i.e. when you
need to overload operators.

I (all) other cases you don't need them.

Please tell me your errors and post the code where the error occurs.


//Sry if my english isn't the best i'm from germany ;-)
 
R

rory

16 C:\Documents and Settings\Rory Walsh\Desktop\test\Untitled1.cpp
expected primary-expression before '->' token

I know now that this error is because my function has no idea what
myfristclass is. Anyway I understand now the idea of a friend function.
But back to my problem, here is the prototype for my start thread
function

PUBLIC void *csoundCreateThread(uintptr_t (*threadRoutine)(void *),
void *userdata);

And in my application I have my thread function

uintptr_t csThread(void *clientData)
{
//code
}

The thing is that I want to be able to access class members in my
csthread function, only this function cannot be part of my main class
as if I do that I get an error:

113 D:\MyDocuments\SourceCode\cabbage\wxCabbage.cpp argument of type
`uintptr_t (Cabbage::)(void*)' does not match `uintptr_t (*)(void*)'

where Cabbage is the name of my main class. Of course this error makes
sense to me, I just can't think of how access my main class member from
within this function? Thanks again for your help, Ihr English ist sehr
gut, and much better than my German! Danke.

Rory.
 
K

KasF

:-D

Another way to solve this problem is to make the main class member
static and the you are able to access them from overall.

class Mylass {

public:
static int number; //deklration
....
};

int Myclass::number; //definition

void myfunc()
{
cout<<Myclass::number;
}

If you have a static member the member are in all object of your class
the same.
It exist only one of them.
And you are able to access them from overall ;-)
 
R

rory

threadID = csoundCreateThread((uintptr_t(*)(void *))csThread, (void
*)pd);

That's the line that creates the error if I don't declare csThread as a
member function. If I declare it as a friend it works fine, only I
can't access members of my class. I see what you mean about declaring
it as static but what's the difference between that and simply using a
global variable? Sorry if my questions don't make much sense, I'm knew
to C++, even though I have been using Borland's C++ Builder for years!
It's only whne I step out of that environment that I realise how little
I know! Thansk again,
Rory.
 
?

=?ISO-8859-1?Q?Stefan_N=E4we?=

rory said:
threadID = csoundCreateThread((uintptr_t(*)(void *))csThread, (void
*)pd);

That's the line that creates the error if I don't declare csThread as a
member function. If I declare it as a friend it works fine, only I
can't access members of my class. I see what you mean about declaring
it as static but what's the difference between that and simply using a
global variable? Sorry if my questions don't make much sense, I'm knew
to C++, even though I have been using Borland's C++ Builder for years!
It's only whne I step out of that environment that I realise how little
I know! Thansk again,
Rory.
I think it's covered here:

http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2


/S
 
K

KasF

You call your function wrong:

I think you should call it so:

threadID = csoundCreateThread(csThread, (void
*)pd);

The first parameter "uintptr_t (*threadRoutine)(void *)" of the
function means that it needs a pointer to a function with the return
value uintptr_t which haves one parameter with the typ void*.

And your function csThread is exactly this function.
And when you only write csThread as argument you get the pointer of the
function. So that's what your csoundCreateThread needs ;-)

Test it out. I'm not sure about it. (If an error occurs please post the
error again and the typ of pd too)

Now to static :
Right! In this situations it makes no huge difference beetween a global
variable and a static.

Normally your static variable is private in your class and all objects
of this class have the same variable, i.e. you can count how much
object exist and then you can get the value from any object.
 
K

KasF

Oh sry, its wrong what I say. I understand it wrong.
Make csThread in your class to a static member function and your
problem will be resolved or you need pointer to member-functions ;-)
 
R

rory

Yes that works, so long as csthread is a friend function, otherwise I
get the same error as before. I guess I could just use glabal
variables. I was trying to keep thing nice and organised though. Anyway
I think it's only going to be a few variable so it's not that bad.
Thanks for your help. I'll check out that link you posted. Cheers,
Rory.
 
A

Ahmed Samieh

rory said:
#include <iostream>
using namespace std;

class myfirstclass
{
private:
public:
int number;
void greeting();
friend void test();
};

void test()
{
cout << myfirstclass->number;
}

1 - number is public so you don't to make a friend function to access
it
2 - myfirstclass is the class name not an object of class so you can't
use it's name or the '->' token to access number
so u got
expected primary-expression before '->' token
whatever, i understand what do u try to do, listen:

you don't need to make friend function but you need to do like this

class MyClass {
.....
};

uintptr_t csThread(void *clientData)
{
MyClass* myObj = clientData;
//code
// to access object members use 'myObj->'

}

to call csoundCreateThread from any object of MyClass
csoundCreateThread(csThread, (void *) this); /* this : pointer to the
object of MyClass type*/

if it is not clear, post a snippet of ur code show what do u wanna to
do exactly
 
R

rory

That's a good solution! I have another function however, a callback
function which is declared as:

void csoundMessageCall(CSOUND* csound, int attr, const char* format,
va_list valist)

Your solution to the previous problem won't work here will it? Any
ideas? Thanks again,

Rory.
 
A

Ahmed Samieh

rory said:
That's a good solution! I have another function however, a callback
function which is declared as:

void csoundMessageCall(CSOUND* csound, int attr, const char* format,
va_list valist)

Your solution to the previous problem won't work here will it? Any
ideas? Thanks again,

Rory.

post the prototybe of class
where u wanna create thread

i did it before - class that need to create thread internally - you can
pass any number of data to the callback function using inside a
structure

Ahmed
 
R

rory

Here is the prototype for the csoundSetMessageCallback, which I pass my
callback function to

PUBLIC void csoundSetMessageCallback(CSOUND *,
void (*csoundMessageCallback_)(CSOUND *,
int attr,
const char
*format,
va_list
valist));
Here is how I call it in my code:
csoundSetMessageCallback(instance, csoundMessageCall);

and here is the actual code for my callback function
void csoundMessageCall(CSOUND* csound, int attr, const char* format,
va_list valist)
{
//would lilke to access members of my main class here......
}


Your other suggestions worked fine with regards the thread function,
thanks for that.

Rory.
 
A

Ahmed Samieh

ammm,
post the prototybe of class
where u wanna create thread

look for example the prototype of my class like this
class MyClass {
private:
HANDLE hThread;
DWORD dwThreadID;
public:
MyClass() {};
void SetupThread();
void Proc();
void RunThread();
~MyClass() {};
};
the prototype of external function like this
DWORD WINAPI ThreadFunction(MyClass * const lpMyObject);

now where to create my thread ?

void MyClass::SetupThread() {
hThread = CreateThread(NULL, // Pointer to Security Attributes
0, // Stack Size The Same Size As
Primary Thread Of The Process
(LPTHREAD_START_ROUTINE)
ThreadFunction, // Address Of Thread Function
this, // Argument For New Thread
Function (the pointer to the object)
CREATE_SUSPENDED, // Creation
Flags
&dwThreadID); // address of thread
id
}
inside the class method named SetupThread, it will call the external
function named ThreadFunction , and will pass a pointer to the caller
object 'this'

when the thread resumed the function ThreadFunction will executed and
will call Proc() from the pointer passed to it like this
DWORD WINAPI ThreadFunction(MyClass * const lpMyObject) {
lpMyObject->Proc();
return 0;
}
now did i need to pass data to Proc() ? no, why ? coz all data that i
need exected in the object data members

if it is clear now , ok, else post ur code to understand ur problem

Ahmed
 
R

rory

Thanks again Ahmed, but as I mentioned in the revious post my thread is
working fine now and I can pass all my members to it as you suggest.
It's the callbcak function which I posted in Message 16 which is the
problem as I can't change the function prototype.

Rory.
 

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

No members online now.

Forum statistics

Threads
474,183
Messages
2,570,967
Members
47,518
Latest member
RomanGratt

Latest Threads

Top