Friend in Class Can't Access Private Function

B

Bryan Parkoff

CMain Class is the base class that is initialized in main function. CA
Class is the base class that is initialized in CMain::CMain(). CMain Class
is always public while CA Class is always private. I have placed "friend
void CA::Run_A(void)" in CMain Class. CMain::Run() function attempts to
execute CA::Run_A(), but compiler shows an error saying that it is the
violation to access private function.
I don't understand why because friend should be able to access private
function. Please advise.

/* A.h */
class CMain;

class CA
{
public:
CA(CMain* pMain);
~CA();

private:
CA();
void Run_A(void);
CMain* m_pMain;
};

/* A.cpp */
#include "A.h"

CA::CA()
{

}

CA::CA(CMain* pMain)
{
m_pMain = pMain;
}

CA::~CA()
{

}

void CA::Run_A(void)
{

}

#include <stdio.h>
#include "A.h"

class CMain
{
public:
CMain();
~CMain();
void Run(void);
friend void CA::Run_A(void);

private:
CA* m_pA;
};

CMain::CMain()
{
m_pA = new CA(this);
}

CMain::~CMain()
{
delete m_pA;
}

void CMain::Run(void)
{
CA::Run_A();
}

void main(void)
{
CMain Main;
}
 
L

Leor Zolman

CMain Class is the base class that is initialized in main function. CA
Class is the base class that is initialized in CMain::CMain(). CMain Class
is always public while CA Class is always private. I have placed "friend
void CA::Run_A(void)" in CMain Class. CMain::Run() function attempts to
execute CA::Run_A(), but compiler shows an error saying that it is the
violation to access private function.
I don't understand why because friend should be able to access private
function. Please advise.

You have two problems. Firstly, your CMain class is trying to "claim"
friendship of that function in CA. That's not how it works. The class with
the thing you need access to must /grant/ friendship to the class needing
the access. So you put something like
friend class CMain;
into CA's class definition (or you can limit it to specific functions, as
you've shown you have the general idea about.)

The other thing is that you're calling a member function as if it were a
static function. See below...
/* A.h */
class CMain;

class CA
{
public:
CA(CMain* pMain);
~CA();

private:
CA();
void Run_A(void);
CMain* m_pMain;
};

/* A.cpp */
#include "A.h"

CA::CA()
{

}

CA::CA(CMain* pMain)
{
m_pMain = pMain;
}

CA::~CA()
{

}

void CA::Run_A(void)
{

}

#include <stdio.h>
#include "A.h"

class CMain
{
public:
CMain();
~CMain();
void Run(void);
friend void CA::Run_A(void);

private:
CA* m_pA;
};

CMain::CMain()
{
m_pA = new CA(this);
}

CMain::~CMain()
{
delete m_pA;
}

void CMain::Run(void)
{
CA::Run_A();

Above, you can do something like:
m_pA -> Run_A();
(after your classes have made friends) but you can't call a member function
without an object to invoke it on.
-leor
 
L

Leor Zolman

(after your classes have made friends) but you can't call a member function
without an object to invoke it on.

I'm getting tired. The two places whre I said "member function", what I
really meant was "non-static" member function.
-leor
 
B

Bryan Parkoff

Leor,

Thank you for the answer. If I place "friend class CMain" in CA class,
all functions and data members will be accessed by CMain class. I do not
allow to happen. What is another way to allow only one private function be
accessed as friend? I don't understand what you mean static or non static
function like outside of class. Please explain.
 
L

Leor Zolman

Leor,

Thank you for the answer. If I place "friend class CMain" in CA class,
all functions and data members will be accessed by CMain class. I do not
allow to happen. What is another way to allow only one private function be
accessed as friend?

In your CA class definition, put:
friend void CMain::Run(void);
to make just that one function of CMain a friend of CA. Since you'd done
this "backwards" in the first place, I just figured you were familiar with
the syntax.

Note that you'll have some ordering issues; I had to put the CMain class
definition up before the CA class definition so that when (in CA) you
declare CMain::Run to be a friend, the compiler recognizes Run as being a
member function of CMain.
I don't understand what you mean static or non static
function like outside of class. Please explain.

All your functions are non-static; that is, they don't use the word
"static" in their declarations. That means they operate upon an object of
their class, not "in a vacuum". Here's your CMain::Run implementation:

void CMain::Run(void)
{
// CA::Run_A();
m_pA->Run_A();
}

The commented-out line is the one you originally had. It says "run the
CA::Run_A() function". But that function can't run without a CA object to
invoke it on. That syntax would only work if CA was a base class of CMain
and had a Run_A function, or if CA::Run_A was a static member function.

This is basic stuff; if you have a C++ book handy, just look up "static
member function".

HTH,
-leor
 
B

Bryan Parkoff

In your CA class definition, put:
friend void CMain::Run(void);
to make just that one function of CMain a friend of CA. Since you'd done
this "backwards" in the first place, I just figured you were familiar with
the syntax.

Note that you'll have some ordering issues; I had to put the CMain class
definition up before the CA class definition so that when (in CA) you
declare CMain::Run to be a friend, the compiler recognizes Run as being a
member function of CMain.
It is very close, but one problem exists. I already put "friend void
CMain::Run(void);" inside CA class. The error compiler reports, "C2027: use
of undefined type 'CMain' and see declaration of 'CMain' ".
I made sure to put definition there. I did put "#include "CMain.h"" and
"class CMain;" in A.h and A.cpp. Look at my code below. Please correct my
error.

/////////////////////////////////////////////////////////////////////
#include "CMain.h"

class CMain;

class CA
{
public:
friend void CMain::Run(void);
CA(CMain* pMain);
~CA();

private:
CA();
void Run_A(void);
CMain* m_pMain;
int test;
};
////////////////////////////////////////
////////////////////////////////////////
#include "A.h"
#include "CMain.h"

CA::CA()
{

}

CA::CA(CMain* pMain)
{
m_pMain = pMain;
test = 1024;
}

CA::~CA()
{

}

void CA::Run_A(void)
{

}

Bryan Parkoff
 
L

Leor Zolman

It is very close, but one problem exists. I already put "friend void
CMain::Run(void);" inside CA class. The error compiler reports, "C2027: use
of undefined type 'CMain' and see declaration of 'CMain' ".
I made sure to put definition there. I did put "#include "CMain.h"" and
"class CMain;" in A.h and A.cpp. Look at my code below. Please correct my
error.

You don't seem to have shown us CMain.h (and please, please always indicate
the filename of files you post, if there's more than one... best thing is a
comment at the top of the file with the file name, and white space
after...for /each/ file. And include /all/ the files! Thanks.)

The compiler is saying that at the point of that error, it still hasn't
seen the definition for CMain. Here's my test version from yesterday that
does compile; with any luck you'll figure out what you've done wrong by
comparing the ordering of things:


/* A.h */
class CA;

class CMain
{
public:
CMain();
~CMain();
void Run(void);

private:
CA* m_pA;
};

class CA
{
friend void CMain::Run(void);
public:
CA(CMain* pMain) {}
~CA() {}

private:
CA();
void Run_A(void) {}
CMain* m_pMain;
};


// ta.cpp:

#include <stdio.h>
#include "A.h"

CMain::CMain()
{
m_pA = new CA(this);
}

CMain::~CMain()
{
delete m_pA;
}

void CMain::Run(void)
{
// CA::Run_A();
m_pA->Run_A();
}

void main(void)
{
CMain Main;
}


-leor
 
G

Gary Labowitz

/* A.h */
class CA;

class CMain
{
public:
CMain();
~CMain();
void Run(void);

private:
CA* m_pA;
};

class CA
{
friend void CMain::Run(void);
public:
CA(CMain* pMain) {}
~CA() {}

private:
CA();
void Run_A(void) {}
CMain* m_pMain;
};


// ta.cpp:

#include <stdio.h>
#include "A.h"

CMain::CMain()
{
m_pA = new CA(this);
}

CMain::~CMain()
{
delete m_pA;
}

void CMain::Run(void)
{
// CA::Run_A();
m_pA->Run_A();
}

void main(void)
{
CMain Main;
}
Leor, when I compiled your "fixed" program I got the following error.

E:/DPR226/My Files/ta.cpp:23:'main' must return 'int'

Otherwise, it seemed okay.
 
L

Leor Zolman

Leor, when I compiled your "fixed" program I got the following error.

E:/DPR226/My Files/ta.cpp:23:'main' must return 'int'

Otherwise, it seemed okay.

That's what I get for not compiling this with Comeau ;-)

I was just addressing the specific access and ordering issues the OP had
been struggling with, in this case, but of course main should return int.
-leor
 
B

Bryan Parkoff

Leor,

I have compiled successfully. The one problem is that I do not want to
put CMain class in A.h, but it should be in CMain.h. I did put the
declaration of "class CMain;" before the definition of "class CA". Why is
it required that class CMain be having a definition before class CA? I
would not want to put more than one definition of class CMain in each header
files. I have to include all source code for one more time.
Why CMain::Run() is allowed to access int CA::test that is private? I
thought that it is allowed to access private function only. Do you
recommend to add const after CMain::Run () so it would prevent int CA::test
from modification?

/* A.h */
#ifndef A_H
#define A_H

#include "CMain.h"

class CMain;

class CA
{
public:
friend void CMain::Run(void);
CA(CMain* pMain);
~CA();


private:
CA();
void Run_A(void);
CMain* m_pMain;
int test;
};

#endif
/* A.h */
/* A.cpp */
#include "A.h"
#include "CMain.h"

CA::CA()
{

}

CA::CA(CMain* pMain)
{
m_pMain = pMain;
test = 1024;
}

CA::~CA()
{

}

void CA::Run_A(void)
{

}
/* A.cpp */
/* CMain.h */
#ifndef CMAIN_H
#define CMAIN_H

#include "A.h"

class CA;

class CMain
{
public:
CMain();
~CMain();
void Run(void);
void Run2(void);

private:
CA* m_pA;
};

#endif
/* CMain.h */
/* CMain.cpp */
#include "CMain.h"
#include "A.h"

CMain::CMain()
{
m_pA = new CA(this);
}

CMain::~CMain()
{
delete m_pA;
}

void CMain::Run(void)
{
m_pA->Run_A();
m_pA->test = 1;
Run2();
}

void CMain::Run2(void)
{
// m_pA->test = 2;
}
/* CMain.cpp */
/* Main.cpp */
#include <stdio.h>
#include "CMain.h"

void main(void)
{
CMain Main;
Main.Run();
}
/* Main.cpp */
 
L

Leor Zolman

Leor,

I have compiled successfully. The one problem is that I do not want to
put CMain class in A.h, but it should be in CMain.h.

I didn't mean to imply it /should/ be in the same file; I was just trying
to show the shortest possible sample program that illustrates the ordering
dependency. If you have things organized with one class definition per
header file, just make sure the compiler "sees" the CMain class definition
before it tries to compile the CA class definition.
I did put the
declaration of "class CMain;" before the definition of "class CA".
Why is
it required that class CMain be having a definition before class CA?

You aren't allowed to use the name "CMain::run" the way you do in your
friend declaration if the compiler has not yet seen CMain's class
definition. How can the compiler be sure there /is/ a CMain::run() ?
I
would not want to put more than one definition of class CMain in each header
files. I have to include all source code for one more time.
Why CMain::Run() is allowed to access int CA::test that is private?

Because you've declared CMain::Run() to be a friend of CA. That's what
friends are for [for good times, and bad times... ;-) ]
I
thought that it is allowed to access private function only.

It is allowed to access private /everything/. Look, my friend, please find
yourself a C++ book and read up all about the "friend" feature.
Do you
recommend to add const after CMain::Run () so it would prevent int CA::test
from modification?

I have no opinion whether you should make Run a const member function or
not; it depends on what it is supposed to do. Rather than trying to give
you a lesson here on when and where const member functions are appropriate,
I'd prefer to just send you to that same book to look up "const member
functions".

Good luck,
-leor
 
B

Bryan Parkoff

It is allowed to access private /everything/. Look, my friend, please find
yourself a C++ book and read up all about the "friend" feature.

If it is the way how C++ Compiler is designed that it can't accept
incomplete class declaration like "class CMain;" before "class CA", I am not
satisified. I have the book called, "C++ Primer Third Edition by Stanley B.
Lippman and Josee Lajoie" It does explain friend in class, but it does not
say like my example source code here in this newsgroups.

Bryan Parkoff
 

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,994
Messages
2,570,222
Members
46,810
Latest member
Kassie0918

Latest Threads

Top