Permitting access to only a subset of the public methods

F

fgh.vbn.rty

Hi,

I'm not sure if i'm asking the question correctly but anyway here it
is.

Say I have 3 classes - class A, class B, class R.
1) A and B are the building blocks and R is like a repository that
stores objects of A and B.
2) A is at the lowest level and should "know about" only other As. B
should know only about As and other Bs.
3) R has 3 types of public methods - (i) methods to add A,B (ii)
methods to access A, B and (iii) all other methods.

For now I pass a pointer to R to both A and B so that they can access
information from R as required. However, this exposes all public
methods (ie., (i), (ii) and (iii)) of R to both A and B.

How do I change it so that A and B can only access methods of type
(ii)? (The rationale is that A/B will never add another A/B and they
shouldn't be doing anything else related to R). Is there a way to make
a subclass of R called Rsub and pass that pointer to A,B? Is that a
good way to do it?

I have included code below.

Thanks.


#include <iostream>
#include <vector>

using namespace std;

class A;
class B;
class R;

class A {
public:
A (R* r, const int& i) : rp(r), N(i) {}
int getN (void) const { return N; }
void fA (const int& idx)
{
// Access an A object at index idx through rp
}
private:
R* rp;
int N;
};

class B {
public:
B (R* r, const string& s) : rp(r), str(s) {}
string getStr (void) const { return str; }
void fB1 (const int& idx)
{
// Access an A object at index idx through rp
}
void fB2 (const int& idx)
{
// Access a B object at index idx through rp
}
private:
R* rp;
string str;
};

class R {
public:
// Methods to add A, B
// void addA (const int& i) { A a(i); vA.push_back(a); }
// void addB (const string& s) { B b(s); vB.push_back(b); }
void addA (const A& a) { vA.push_back(a); }
void addB (const B& b) { vB.push_back(b); }

// Methods to access information for A,B
int getAN (const int& idx) const { return vA.at(idx).getN(); }
string getBstr (const int& idx) const { return
vB.at(idx).getStr(); }
// ... some more info

// All other methods
// ...
private:
vector<A> vA;
vector<B> vB;
};

int main() {
R rep;

A a1(&rep, 100);
A a2(&rep, 200);
rep.addA(a1);
rep.addA(a2);
cout << rep.getAN(0) << " and " << rep.getAN(1) << endl;

// a2.fA(0); // should return info about a1

B b1(&rep, "dog");
B b2(&rep, "cat");
rep.addB(b1);
rep.addB(b2);
cout << rep.getBstr(0) << " and " << rep.getBstr(1) << endl;

// b2.fB1(0); // should return info about a1
// b2.fB2(0); // should return info about b1

return 0;
}
 
J

Joe Greer

(e-mail address removed) wrote in (e-mail address removed):
Hi,

I'm not sure if i'm asking the question correctly but anyway here it
is.

Say I have 3 classes - class A, class B, class R.
1) A and B are the building blocks and R is like a repository that
stores objects of A and B.
2) A is at the lowest level and should "know about" only other As. B
should know only about As and other Bs.
3) R has 3 types of public methods - (i) methods to add A,B (ii)
methods to access A, B and (iii) all other methods.

For now I pass a pointer to R to both A and B so that they can access
information from R as required. However, this exposes all public
methods (ie., (i), (ii) and (iii)) of R to both A and B.

How do I change it so that A and B can only access methods of type
(ii)? (The rationale is that A/B will never add another A/B and they
shouldn't be doing anything else related to R). Is there a way to make
a subclass of R called Rsub and pass that pointer to A,B? Is that a
good way to do it?

I have included code below.

Thanks.


#include <iostream>
#include <vector>

using namespace std;

class A;
class B;
class R;

class A {
public:
A (R* r, const int& i) : rp(r), N(i) {}
int getN (void) const { return N; }
void fA (const int& idx)
{
// Access an A object at index idx through rp
}
private:
R* rp;
int N;
};

class B {
public:
B (R* r, const string& s) : rp(r), str(s) {}
string getStr (void) const { return str; }
void fB1 (const int& idx)
{
// Access an A object at index idx through rp
}
void fB2 (const int& idx)
{
// Access a B object at index idx through rp
}
private:
R* rp;
string str;
};

class R {
public:
// Methods to add A, B
// void addA (const int& i) { A a(i); vA.push_back(a); }
// void addB (const string& s) { B b(s); vB.push_back(b); }
void addA (const A& a) { vA.push_back(a); }
void addB (const B& b) { vB.push_back(b); }

// Methods to access information for A,B
int getAN (const int& idx) const { return vA.at(idx).getN(); }
string getBstr (const int& idx) const { return
vB.at(idx).getStr(); }
// ... some more info

// All other methods
// ...
private:
vector<A> vA;
vector<B> vB;
};

int main() {
R rep;

A a1(&rep, 100);
A a2(&rep, 200);
rep.addA(a1);
rep.addA(a2);
cout << rep.getAN(0) << " and " << rep.getAN(1) << endl;

// a2.fA(0); // should return info about a1

B b1(&rep, "dog");
B b2(&rep, "cat");
rep.addB(b1);
rep.addB(b2);
cout << rep.getBstr(0) << " and " << rep.getBstr(1) << endl;

// b2.fB1(0); // should return info about a1
// b2.fB2(0); // should return info about b1

return 0;
}

Well, the first thing that comes to mind is to use interfaces.

class IR_A {
public:
virtual void addA(const A& a) = 0;
virtual int getAN(const int& idx) = 0;
virtual ~IR_A(){}
};

class IR_B {
public:
virtual void addB(const B& b) = 0;
virtual string getBstr(const int& idx) = 0;
virtual ~IR_B(){}
};

class R : public IR_A, public IR_B {
public:
// Methods to add A, B
// void addA (const int& i) { A a(i); vA.push_back(a); }
// void addB (const string& s) { B b(s); vB.push_back(b); }
void addA (const A& a) { vA.push_back(a); }
void addB (const B& b) { vB.push_back(b); }

// Methods to access information for A,B
int getAN (const int& idx) const { return vA.at(idx).getN(); }
string getBstr (const int& idx) const { return
vB.at(idx).getStr(); }
// ... some more info

// All other methods
// ...
private:
vector<A> vA;
vector<B> vB;
};

Then, you change your A and B classes to use them...

class A {
public:
A (IR_A * r, const int& i) : rp(r), N(i) {}
int getN (void) const { return N; }
void fA (const int& idx)
{
// Access an A object at index idx through rp
}
private:
IR_A * rp;
int N;
};

class B {
public:
B (IR_B* r, const string& s) : rp(r), str(s) {}
string getStr (void) const { return str; }
void fB1 (const int& idx)
{
// Access an A object at index idx through rp
}
void fB2 (const int& idx)
{
// Access a B object at index idx through rp
}
private:
IR_B * rp;
string str;
};

Main can stay the same. If you want a bit more added security, you can
make all the methods of R which participate in IR_A or IR_B private. Then
you can only access those methods through one of the two interfaces.

Hope that is of some help.

joe
 
M

muralive

I am suspecting a fundamental misunderstanding of the underlying
problem and the simplified case presented here is quite reflecting
that. Anyway, passing a subclass of R to A/B isn't going to be able to
do anything to make certain public methods of R to unavailable to A
and B. I can think of a few solutions based on similar design
patterns, obscurity through encapsulation (containment) or
polymorphically though levels of base classes preferably abstract
(like interfaces in java).
So using your own example, contain R in RCA or RCAB and provide them
to A or B respectively or create a (fully abstract) AR and ABR,
inherit R from them, that is AR->ABR->R, construct R but pass R as AR
or ABR to A or AB respectively.
In both of the above cases, have public only those methods that A or B
should see.

- Murali.
 

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,769
Messages
2,569,581
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top