Why won't this code, implementing PassKey pattern, compile? - c++

Here is the code, c++11 :
#include<stdio.h>
#include<iostream>
template<typename T>
class Passkey
{
friend T;
Passkey() {}
Passkey(const Passkey&) {}
Passkey& operator=(const Passkey&) = delete;
};
class Access;
class MyClass
{
public:
MyClass() {}
private:
void func(Passkey<Access>) { std::cout<<"here" << std::endl;}
};
class Access
{
public:
void tryme(MyClass& c) { c.func(Passkey<Access>());}
};
int main ()
{
MyClass c;
Access a;
a.tryme(c);
return 0;
}
Compiler is giving the following errors:
prog.cpp: In member function 'void Access::tryme(MyClass&)':
prog.cpp:21:12: error: 'void MyClass::func(Passkey<Access>)' is private
void func(Passkey<Access>) { std::cout<<"here" << std::endl;}
^
prog.cpp:27:56: error: within this context
void tryme(MyClass& c) { c.func(Passkey<Access>());}

As pewt said, MyClass::func() must be public in order for Access::tryme() to be able to access it. In the example you linked in the comments, Citizen::getSocialSecurityNumber() is actually public. And that is fine, because the access is limited in a different way.
Your MyClass::func() takes a Passkey<Access> parameter – and no one is actually allowed to construct such an object apart from the Access class itself. All of Passkey's functions are private. By construction, Access is the only friend of Passkey<Access>, so only Access can construct the “key” required to call func(). So func() behaves as if it were private, without actually being private itself.

func() is a private method for MyClass. Access can't call func unless it is made a friend of MyClass.
Making PassKey a friend of Access does not (as far as I know...) allow use of MyClass's private methods.
Via https://en.wikipedia.org/wiki/C%2B%2B_classes#Member_functions
The private members are not accessible outside the class; they can be accessed only through methods of the class.
And When should you use 'friend' in C++?

Related

friend function pointer parameter in constructor

i'm trying to create a costructor in the form
class A {
public:
A(void (*initializer)(A&))
{
initializer(*this);
}
};
where initializer take a reference to the instance he's passed and can make custom operation on variable it is initializing. Is there a way to make such a function friend so it can access to private variables too?
Here is a simple way:
class Impl
{
public:
int x;
int y;
};
class A
{
public:
A(void (*initializer)(Impl&))
{
initializer(_impl);
}
private:
Impl _impl;
};
This hides _impl from everyone except initializer. And since nobody other than initializer can access _impl at all, the members of of class Impl can be public, making it easy for initializer to mutate them.
Other than listing all the functions you want to pass pointers to as friends separately, no. An alternative may be to separate the data into a base class with public members you inherit privately from:
struct AData
{
int m_privateInt;
...
};
class A : private AData {
public:
A(void (*initializer)(AData&))
{
initializer(*this);
}
};
You may need to also pass a reference to A, if you want to access its member functions in initializer.

Why this code is working ? I mean the member is private

why this code is working? I mean the value is a private variable, why function assign() can access it directly?
class A {
private:
int value;
public:
A() :value(0){ }
void assign(A x)
{
value = x.value;
}
};
int main()
{
A a;
A b;
a.assign(b);
return 0;
}
The private keyword means that no code outside the class can access the class.
Methods of the same class can access it, sure, because if they couldn't nobody could access private variables and they'd be useless.
If you worry about the access from the method called for A to the private member of B, don't worry.
The idea of private and public is making the implementation details of the class a thing nobody knows (and needs to know), but the class itself.
The class A "knows" how A itself is implemented, and so is "allowed" to use it's internals - privates, even if they're not of the called object.
Member functions (e.g., A::assign(A)) can access private members of their respective class, in addition to protected members of inherited classes.
int value is private, but void assign(A x) is public. In main function (outside class A) you can access only to public methods. Inside class A (for example in assign method) you can access to public, private and protected members
For example:
You can't write something like this:
A obj;
obj.value;
because value is private.
But you can access it using other methods: for example you can define set(int val) method
class A {
private:
int value;
public:
A() :value(0){ }
void set(int val)
{
value = val;
}
void assign(A x)
{
value = x.value;
}
};
int main()
{
A obj;
obj.set(10);
}

Read private variables class members

I'm new to c++ and I need to read from private class members of a class in a method that's in a different class, for example:
class a{
private:
int x;
}
class b{
void foo();
}
void b::foo(){
//here I want to read from x that's in a
}
Do I have to set up a function in class a like int readx(){return x);) or a readclass(){return *this);}? Is there another way?
The private section of a class has the objective of 'hiding' the way you handle the data, providing a streamlined way of accesing said data with public methods.
The advantage of using a public method to change the value of private members is that you can, for example, allow values only between 0 and 10 for 'x'.
In your case, you should think about what does 'x' represent in your first class, and if it makes sense for the second class to access it directly and without any control or special consideration. If this is the case, it should probably be a public value. In the other case, you will need to make a public method to read it, like your readx example.
If only 'b' has the privilege to access 'x' directly, you can also define a friend function, like someone already said.
Note that returnig a pointer to the instance wouldn't allow access to private members of the class.
You could use friend class or function, but it is a bad idea to use private members of methods (tests are only reasonable excuse for that). Better to use public methods for that or redesign your code if you couldn't avoid usage of private members.
You can implement a friend function that can access x in foo.
Reference
If there is no accessor to this data member in class a then you should declare the member function of class b as a friend function of class a.
For example
#include <iostream>
class B
{
public:
void foo() const;
};
class A
{
public:
A( int x ) : x( x ){}
private:
friend void B::foo() const;
int x;
};
void B::foo() const
{
A a { 10 };
std::cout << a.x << std::endl;
}
int main()
{
B().foo();
return 0;
}
Declaring a friend function or class would grant read and write access to a's x to that function or class, a
class a {
public:
const int& readx() const { return x; }
private:
int x
};
or, if you like that semantics better
class a {
public:
const int& x() const { return x_; }
private:
int x_;
};
grants read access only, but to every client.

Policy inheritance and inaccessible protected members

It seems that a protected member from a template policy class is inaccessible, even with a class hierarchy which seems correct.
For instance, with the following code snippet :
#include <iostream>
using namespace std;
template <class T>
class A {
protected:
T value;
T getValue() { return value; }
public:
A(T value) { this->value = value; }
};
template <class T, template <class U> class A>
class B : protected A<T> {
public:
B() : A<T>(0) { /* Fake value */ }
void print(A<T>& input) {
cout << input.getValue() << endl;
}
};
int main(int argc, char *argv[]) {
B<int, A> b;
A<int> a(42);
b.print(a);
}
The compiler (clang on OS X, but gcc returns the same type of error) returns the following error :
Untitled.cpp:18:21: error: 'getValue' is a protected member of 'A<int>'
cout << input.getValue() << endl;
^
Untitled.cpp:25:5: note: in instantiation of member function 'B<int, A>::print' requested here
b.print(a);
^
Untitled.cpp:8:7: note: can only access this member on an object of type 'B<int, A>'
T getValue() { return value; }
^
1 error generated.
The strange thing is that the last note from the compiler is totally correct but already applied since the b object is of type 'B<int, A>'. Is that a compiler bug or is there a problem in the code ?
Thanks
You have misunderstood the meaning of protected access.
Protected members are callable by derived classes. But only on the base object contained inside the class itself.
For example, if i simplify the problem, using :
class A {
protected:
void getValue(){}
};
class B : protected A
{
public:
void print(A& input)
{
input.getValue(); //Invallid
}
};
getValue cannot be called on a "A" object other than the "A" object inside the class itself.
This for example is valid.
void print()
{
getValue(); //Valid, calling the base class getValue()
}
As pointed out by Dan Nissenbaum and shakurov. This is however also valid:
void print(B& input)
{
input.getValue();
}
This is because we explicitly say that input is a object of B. And the compiler know that all that objects of B has protected access to getValue. In the case when we pass a A&, the object might as-well be a type of C, wich could be derrived from A with private access.
Let's forget for a minute about the template and look at this:
class A {
protected:
int value;
int getValue() { return value; }
public:
A(int value) { this->value = value; }
};
class B : protected A {
public:
B() : A(0) { /* Fake value */ }
void print(A& input) {
cout << input.getValue() << endl;
}
};
The print() method's implementation is wrong because you can't access non-public member of A inside B. And here's why: from within B, you can only access non-public members of B. Those members may be either inherited or not — it doesn't matter.
On the other hand, A& input may not be a reference to an instance of B. It may be a reference to another subclass (which may well have getValue() inaccessible).
Member functions of a derived class have access to protected base class members within any object of its type that is passed as an argument so long as the explicitly declared class of the object passed as an argument is that of the the derived class (or a further derived class).
Objects explicitly passed as the base class type cannot have their protected members accessed within the derived class's member functions.
In other words, if we have:
class A
{
protected:
int x;
}
class B : public A
{
void foo(B b)
{
b.x; // allowed because 'b' is explicitly declared as an object of class B
}
void goo(A a)
{
a.x; // error because 'a' is explicitly declared as having *base* class type
}
};
...then the line a.x is not allowed because the explicit type of the argument is A, but the rule for protected access only applies to objects explicitly defined as the same class as the class attempting to access the member. (...Or a class derived from it; i.e., if class Cderives from B, then passing an object explicitly declared as an object of class C will also have x accessible within B member functions.)
The reason for this is given by shakurov when he writes (paraphrasing)
A& input might not be a reference to an instance of B. It may be a
reference to another subclass (which may well have getValue()
inaccessible)
An excellent explication of this answer is also given here: accessing a protected member of a base class in another subclass.
As a matter of interest, I believe that this comes from the C++ standard here:
11.4 Protected member access [class.protected] 1 An additional access check beyond those described earlier in Clause 11 is applied when a
non-static data member or non-static member function is a protected
member of its naming class (11.2)115 As described earlier, access to a
protected member is granted because the reference occurs in a friend
or member of some class C. If the access is to form a pointer to
member (5.3.1), the nested-name-specifier shall denote C or a class
derived from C. All other accesses involve a (possibly implicit)
object expression (5.2.5). In this case, the class of the object
expression shall be C or a class derived from C.
Don't get distracted by the template. It has nothing to do with the error. The line in main that the compiler is complaining about creates an object of type B<int, a> and tries to access a protected member. That's not legal, regardless of the type. You can only use protected members from inside a member function or friend function. For example:
struct S {
protected:
void f();
};
int main() {
S s;
s.f(); // error: attempts to call a protected member function
}

Access to method pointer to protected method?

This code:
class B {
protected:
void Foo(){}
}
class D : public B {
public:
void Baz() {
Foo();
}
void Bar() {
printf("%x\n", &B::Foo);
}
}
gives this error:
t.cpp: In member function 'void D::Bar()':
Line 3: error: 'void B::Foo()' is protected
Why can I call a protected method but not take its address?
Is there a way to mark something fully accessible from derived classes rather than only accessible from derived classes and in relation to said derived class?
BTW: This looks related but what I'm looking for a reference to where this is called out in the spec or the like (and hopefully that will lead to how to get things to work the way I was expecting).
You can take the address through D by writing &D::Foo, instead of &B::Foo.
See this compiles fine : http://www.ideone.com/22bM4
But this doesn't compile (your code) : http://www.ideone.com/OpxUy
Why can I call a protected method but not take its address?
You cannot take its address by writing &B::Foo because Foo is a protected member, you cannot access it from outside B, not even its address. But writing &D::Foo, you can, because Foo becomes a member of D through inheritance, and you can get its address, no matter whether its private, protected or public.
&B::Foo has same restriction as b.Foo() and pB->Foo() has, in the following code:
void Bar() {
B b;
b.Foo(); //error - cannot access protected member!
B *pB = this;
pB->Foo(); //error - cannot access protected member!
}
See error at ideone : http://www.ideone.com/P26JT
This is because an object of a derived class can only access protected members of a base class if it's the same object. Allowing you to take the pointer of a protected member function would make it impossible to maintain this restriction, as function pointers do not carry any of this information with them.
I believe protected doesn't work the way you think it does in C++. In C++ protected only allows access to parent members of its own instance NOT arbitrary instances of the parent class. As noted in other answers, taking the address of a parent function would violate this.
If you want access to arbitrary instances of a parent, you could have the parent class friend the child, or make the parent method public. There's no way to change the meaning of protected to do what you want it to do within a C++ program.
But what are you really trying to do here? Maybe we can solve that problem for you.
Why can I call a protected method but not take its address?
This question has an error. You cannot do a call either
B *self = this;
self->Foo(); // error either!
As another answer says if you access the non-static protected member by a D, then you can. Maybe you want to read this?
As a summary, read this issue report.
Your post doesn't answer "Why can I
call a protected method but not take
its address?"
class D : public B {
public:
void Baz() {
// this line
Foo();
// is shorthand for:
this->Foo();
}
void Bar() {
// this line isn't, it's taking the address of B::Foo
printf("%x\n", &B::Foo);
// not D:Foo, which would work
printf("%x\n", &D::Foo);
}
}
Is there a way to mark something fully accessible from derived classes rather than only accessible from derived classes and in relation to said derived class?
Yes, with the passkey idiom. :)
class derived_key
{
// Both private.
friend class derived;
derived_key() {}
};
class base
{
public:
void foo(derived_key) {}
};
class derived : public base
{
public:
void bar() { foo(derived_key()); }
};
Since only derived has access to the contructor of derived_key, only that class can call the foo method, even though it's public.
The obvious problem with that approach is the fact, that you need to friend every possible derived class, which is pretty error prone. Another possible (and imho better way in your case) is to friend the base class and expose a protected get_key method.
class base_key
{
friend class base;
base_key() {}
};
class base
{
public:
void foo(base_key) {}
protected:
base_key get_key() const { return base_key(); }
};
class derived1 : public base
{
public:
void bar() { foo(get_key()); }
};
class derived2 : public base
{
public:
void baz() { foo(get_key()); }
};
int main()
{
derived1 d1;
d1.bar(); // works
d1.foo(base_key()); // error: base_key ctor inaccessible
d1.foo(d1.get_key()); // error: get_key inaccessible
derived2 d2;
d2.baz(); // works again
}
See the full example on Ideone.
Standard reference: https://en.cppreference.com/w/cpp/language/access#Protected_member_access
When a pointer to a protected member is formed, it must use a derived class in its declaration:
struct Base {
protected:
int i;
};
struct Derived : Base {
void f() {
// int Base::* ptr = &Base::i; // error: must name using Derived
int Base::* ptr = &Derived::i; // OK
}
};