friend function pointer parameter in constructor - c++

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.

Related

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);
}

Making parent class members unmodifiable for each derived class

I'm wondering how can I make unmodifiable a parent class member which will be different for each derived class.
My code now assigns its value correctly (depending on the Child class that calls the parent class' constructor), but m_type can be easily modified (in myfunction, for example) and that's what I'd like to avoid.
#include <iostream>
enum Piece_type{ king=1, queen=3, rook=3, bishop=4, knight=5, pawn=6};
class Piece
{
protected:
Piece_type m_type; // static Piece_type m_type; <- doesn't work
Piece(Piece_type ex): m_type(ex) {}
};
class Pawn: public Piece
{
public:
Pawn():Piece(pawn) {} // To initialise m_type as pawn for all my Pawn objects
void myfunction()
{
std::cout<<"My piece type is "<< m_type<<std::endl;;
m_type= knight; // This is the assignation I want to avoid happening
std::cout<<"My new piece type i "<<m_type<<std::endl;
}
};
My question is related to this one, but inheritance doesn't seem to make possible to declare a static variable and define its value through a member initializer.
I've found how to call the parent/base class constructor from the Child class in this question.
Thanks in advance,
Eduardo
Edit
I've slightly modified it so that not to confuse anyone, because const does work where I said it didn't.
Well, you didn't fall into the usual mistake of trying to use const member variables without a member initializer list, so const is all you need really:
class Piece
{
protected:
Piece_type const m_type;
Piece(Piece_type ex) : m_type(ex) { }
};
class Pawn : public Piece
{
public:
Pawn() : Piece(pawn) { }
void myfunction()
{
// m_type = knight; // Compile-time error
}
};
They only ways to prevent a derived type from modifying it's parent's members is to make those members private or const. Since you can't make the member const the only other way would be to declare the member private and adding a protected accessor method such as :
Piece_type get_type() const
{
return m_type;
}
This way, derived classes can call get_type() to know m_type's value but can't access it directly, preventing them from writing to it.

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.

Why do C++ classes not have access specifiers like classes in Java have?

I'm new to C++, and I'm familiar with Java. The first thing I was wondering about when I started looking at C++ code is that classes themselves (not the members) don't have access specifiers such private, protected and public. Exemples here and here.
public class A { // This line.
private class B { } // Not this line.
}
Why is that so?
There's no access modifier at the level of classes, since the language has no concept of package. But there is at the level of data members, member functions and inheritence:
class Foo {};
class Bar : public Foo {
public:
void bar() const {}
private:
int bar_(float) {}
int a, b, c;
};
The closest you can get is declaring nested classes inside a class:
class Foo {
struct Bar0 {
void bar0() const {}
};
struct Bar1 {
Bar0 b0;
Bar1() { b0.bar0();}
};
};
There's no need for class-level access specifier. If you want a private class, you can define it in an implementation file or an anonymous namespace. This sort of restriction is done at file-level for C++ (i.e. how you organize your headers, preprocessor directives).
Before edit:
They do, but they're not per-method. Also, classes have a default private specifier, so, unless otherwise noted, they are private.
class A
{
void foo(); //private
};
class B
{
void foo(); //private
public:
void foo1(); //public
void foo2(); //public
protected:
void foo3(); //protected
private:
void foo4(); //private
};
Note 1 C++ also has struct, which is identical to a class except the default access level is public.
Note 2 There is no package-scope in C++. In Java, protected gives access to the whole package, in C++ it just gives access to deriving classes.
Note 3 The friend keyword can be used to bypass restrictions, look it up.
C++ uses a slightly different syntax where access modifiers are specified for groups of declarations instead of individually:
class Test {
class MyPrivateClass {
// ...
};
void privateByDefault();
public:
void myPublicFunction();
void anotherPublicFunction();
private:
void myPrivateFunction();
public:
class MyPublicClass {
// ...
};
void morePublicFunctions();
protected:
// ...
};
Test::MyPrivateClass is inaccessible outside of Test, while Test::MyPublicClass can be used anywhere.
From your source: http://www.cplusplus.com/doc/tutorial/classes
private members of a class are accessible only from within other
members of the same class or from their friends. protected members are
accessible from members of their same class and from their friends,
but also from members of their derived classes. Finally, public
members are accessible from anywhere where the object is visible.

invalid use of non-static data member

For a code like this:
class foo {
protected:
int a;
public:
class bar {
public:
int getA() {return a;} // ERROR
};
foo()
: a (p->param)
};
I get this error:
invalid use of non-static data member 'foo::a'
currently the variable a is initialized in the constructor of foo.
if I make it static, then it says:
error: 'int foo::a' is a static data member; it can only be initialized at its definition
However I want to pass a value to a in the constructor.
What is the solution then?
In C++, unlike (say) Java, an instance of a nested class doesn't intrinsically belong to any instance of the enclosing class. So bar::getA doesn't have any specific instance of foo whose a it can be returning. I'm guessing that what you want is something like:
class bar {
private:
foo * const owner;
public:
bar(foo & owner) : owner(&owner) { }
int getA() {return owner->a;}
};
But even for this you may have to make some changes, because in versions of C++ before C++11, unlike (again, say) Java, a nested class has no special access to its enclosing class, so it can't see the protected member a. This will depend on your compiler version. (Hat-tip to Ken Wayne VanderLinde for pointing out that C++11 has changed this.)
In C++, nested classes are not connected to any instance of the outer class. If you want bar to access non-static members of foo, then bar needs to have access to an instance of foo. Maybe something like:
class bar {
public:
int getA(foo & f ) {return foo.a;}
};
Or maybe
class bar {
private:
foo & f;
public:
bar(foo & g)
: f(g)
{
}
int getA() { return f.a; }
};
In any case, you need to explicitly make sure you have access to an instance of foo.
The nested class doesn't know about the outer class, and protected doesn't help. You'll have to pass some actual reference to objects of the nested class type. You could store a foo*, but perhaps a reference to the integer is enough:
class Outer
{
int n;
public:
class Inner
{
int & a;
public:
Inner(int & b) : a(b) { }
int & get() { return a; }
};
// ... for example:
Inner inn;
Outer() : inn(n) { }
};
Now you can instantiate inner classes like Inner i(n); and call i.get().
You try to access private member of one class from another. The fact that bar-class is declared within foo-class means that bar in visible only inside foo class, but that is still other class.
And what is p->param?
Actually, it isn't clear what do you want to do
Your Question is not clear but there is use case when you will get this issue .
Invalid use of non-static data member.
When you are using "non-static data member in another class try to not use with scope resolution operator
Example::className::memberData = assignivalue ;
instead of above try to use object of className class;
Example:: m_pClassName->memberData=assignValue;*