[Not solved]Allow access to Private from external object method

Hi, I can not give access permission to a single method of a struct to another private structure part .
The code only work if I declare the complete spy structure like a friend,
but throw error if i try a single method friend: friend void spy::stealInfo(info *i);

I do not want to change the objects order, because later, I want declare a new method in info, that like friend can to "spy" private part access


please somebody so kind to help me?
Thanks in advance.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <string>

using namespace std;

class spy;


class info {
    //impose private
    string secretInfo = "Secret Info";
  public:
    friend void spy::stealInfo(info *i);  
};

//*****************************************
//*****************************************

class spy {
    //impose private
    string stolenInfo = "";

  public:
    void stealInfo(info *i);
};
//----
    void spy::stealInfo(info *i){
        stolenInfo = i->secretInfo;
    }

//***********************************
int main(void)
{

}


List of Issues:
main.cpp:13: error: invalid use of incomplete type 'class spy'
friend void spy::stealInfo(info*);

main.cpp:6: forward declaration of 'class spy'
class spy;

main.cpp:-1: In member function 'void spy::stealInfo(info*)':

main.cpp:11: error: 'std::__cxx11::string info::secretInfo' is private
string secretInfo = "Secret Info";
^
main.cpp:28: error: within this context
stolenInfo = i->secretInfo;

Last edited on
You need to put the class definition of spy before the class definition of info.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class info;

class spy {
    string stolenInfo = "";
  public:
    void stealInfo(info *i);
};

class info {
    string secretInfo = "Secret Info";
  public:
    friend void spy::stealInfo(info *i);  
};

void spy::stealInfo(info *i){
	stolenInfo = i->secretInfo;
}
thank you peter, but "I do not want to change the objects order, because later, I want declare a new method in info, that like friend can to "spy" private part access"
The goal is: (but don't works)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <string>

using namespace std;

class spy;



class info {
    //impose private
    string secretInfo = "Secret Info";
  public:
    void isInfoStolen(spy *s); //-----------
    friend void spy::stealInfo(info *); // <-That don't work
    //friend class spy; //that works

};



//*****************************************
//*****************************************

class spy {
    //impose private
    string stolenInfo = "";

  public:
    void stealInfo(info *);
    friend void info::isInfoStolen(spy *s);
};

//ffffffff
void spy::stealInfo(info *i){
    stolenInfo = i->secretInfo;
}

//--------
void info::isInfoStolen(spy *s){
    if(secretInfo == s->stolenInfo) cout << "The info was stolen" << endl;
}

int main(void)
{
    info i;
    spy s;

    s.stealInfo(&i);
    i.isInfoStolen(&s);
}
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <string>

using namespace std;

class spy;



class info {
    //impose private
    string secretInfo = "Secret Info";
  public:
    info(const std::string& s) : secretInfo(s){};
    void isInfoStolen(spy *s); //-----------
    //friend void spy::stealInfo(info *); // <-That don't work
    //friend class spy; //that works
    string returnSecret()const{return secretInfo;}

};



//*****************************************
//*****************************************

class spy {
    //impose private
    string stolenInfo = "";

  public:
    void stealInfo(info *);
    friend void info::isInfoStolen(spy *s);
    string returnStolen()const{return stolenInfo;}
    void print()const{std::cout << stolenInfo << '\n';}
};

//ffffffff
void spy::stealInfo(info *i){
    stolenInfo = i->returnSecret();
}

//--------
void info::isInfoStolen(spy *s){
    if(secretInfo == s->stolenInfo) cout << "The info was stolen" << endl;
}

int main(void)
{
    info i(std::string("Secret"));
    spy s;

    s.stealInfo(&i);
    i.isInfoStolen(&s);
    s.print();
}

If anything is unclear give a shout
If I'm understanding you correctly, both spy and info will have friend methods declared in the other class.

1
2
3
4
5
class info
{
  // ... stuff ...
  friend void spy::stealInfo(info*);
}


and

1
2
3
4
5
class spy
{
  //... stuff
  friend void info::spyStuff(spy*);
}


The problem is that, with mutually friendly methods, the info class needs to see the entire spy class to know that it has the stealInfo() method. A forward declaration won't do since info needs to see the method. So, the spy class neds to come before the info class. But, for the same reasoning, the info class needs to come before spy in order to make the friend void info::spyStuff() declaration work. This contradiction means that the code you want can't be written.

There are other options. You could make the classes friends class info { friend class spy; } and vice versa. Or, you could forget friends and make public functions that take the other class as arguments.

Perhaps something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <string>
#include <iostream>

using namespace std;

class spy;

class info
{
  private:
    string secretInfo = "133+ p@55vv0|2dz";
  public:
    void letInfoBeStolen(spy*); // passing spy by non-const reference would be better
    void tripAlarm();
};


class spy
{
  private:
    string stolenInfo;
  public:
    void stealInfo(string s);
    void tripOverAlarm(info*);
};


void info::letInfoBeStolen(spy* s)
{
  s->stealInfo(secretInfo);
  s->tripOverAlarm(this);
}

void info::tripAlarm()
{
  cout << "ALARM!" << endl;
}

void spy::stealInfo(string s)
{
  stolenInfo = s;
  cout << "I got the data! : " << stolenInfo << endl;
}

void spy::tripOverAlarm(info* i)
{
  i->tripAlarm();
  cout << "Uh oh ..." << endl;
}



int main()
{
  info information;
  spy spyMaster;
  information.letInfoBeStolen(&spyMaster);

  return 0;
}


This results in:
I got the data! : 133+ p@55vv0|2dz
ALARM!
Uh oh ...

Since info only needs to know about the spy for an argument, a forward declaration works. It will also be easy to add more methods to either class. The other important thing is that the arguments enforce the fact that only spys can get at the private data.

I admit it breaks the image of a spy secretly stealing private data, but that's a small price to pay for working code.
You can do this with pointer hacks as well. It might take a little hands-on work to get the right offset, but it is a well known approach. You have to do this once in a while if you have a black-box library that does not allow access to something that you needed. You can write a function that takes a void pointer, pass in the class object, convert that to a unsigned char pointer, and iterate over it looking for something. When you find what you seek, you can get that address and then you own it, you can get it, you can set it, etc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
#include <string>

class control;
class kaos;
class uncle;

class uncle{
	friend control;
	friend kaos;
private:
	std::string napoleon_solo(kaos *);
	std::string illya_kuryakin(control *);
};

class kaos{
	friend std::string uncle::napoleon_solo(kaos*);
private:
	std::string stolen_info;
public:
	void siegfried(control *);
};

class control{
	friend std::string uncle::illya_kuryakin(control *);
private:
	std::string secret_info = "swordfish";
public:
	void maxwell(kaos *);
};

void kaos::siegfried(control *agent){
	uncle tom;
	this->stolen_info = tom.illya_kuryakin(agent);
}

void control::maxwell(kaos *agent){
	uncle tom;
	if(this->secret_info == tom.napoleon_solo(agent))
		std::cout << "I think we should use the cone of silence.\n";
}

std::string uncle::napoleon_solo(kaos *agent){
	return agent->stolen_info;
}

std::string uncle::illya_kuryakin(control *agent){
	return agent->secret_info;
}

int main(){
	kaos boss;
	control chief;

	boss.siegfried(&chief);
	chief.maxwell(&boss);
}
Topic archived. No new replies allowed.