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;*
Related
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.
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.
Alright, so I've tried a few ways to deal with this issue, but I can't seem to fix it.
In my header file I have:
class MyClass {
public:
bool test;
struct MyStruct;
};
I also have a constructor and all that, but that's not the important/not causing errors
In the cpp what I want to do is this:
MyClass::MyStruct {
test=true;
};
The problem with this, is that the struct is unable to access the test variable. How can I pass the current instance's variable to the struct or some other way to allow the struct to access the variable.
This:
MyClass::MyStruct {
test=true;
};
Is not at all valid C++ code. Perhaps you meant this:
MyClass::Class() {
test=true;
}
Which would make a default constructor of MyClass which sets test to true. But your question makes it seem like you want to set the value of MyClass::test from MyClass::MyStruct. This is not really possible, because a nested class (or struct, in your case) does not "inherit" or "contain" or really have almost any special relationship with its enclosing class (or struct).
Another possibility is this:
class MyClass {
public:
static bool test;
struct MyStruct;
};
MyClass::MyStruct::MyStruct() {
test=true;
}
Which would make a default constructor of the nested struct which sets a variable in the enclosing class, but the variable then needs to be static, meaning there's only one in the whole program, not a separate value per instance of either class or struct.
Seems to me if MyStruct is executing code it should be a class. And if so, you either pass it an instance of the MyClass (e.g. this if calling from MyClass), or pass it a reference to the member it needs (e.g. this->test)...
You can declare the structure as a friend in the class definition.
class MyClass {
public:
bool test;
friend struct MyStruct;
};
Edit:
class MyClass {
friend class MyStruct(MyClass *myClass) : myClass(myClass) {
private:
MyClass *myClass;
}
MyStruct *myStruct;
bool test;
public:
MyClass() {
myStruct = new MyStruct(this);
}
}
Note: This is untested and just written in my browser. I know it's missing destructors and stuff.
Since you're passing the parent pointer to the member class, the member class can then access the parent class's private members because it was declared a friend.
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
}
I want to create a member function with the same name of the returning type. Example:
class A { };
class B {
public:
A& A() { return *a; }
private:
A* a;
};
However, the compiler won't let me. I tried to change the type of the member return type to ::A (as sugested here, but with no avail. I know I could just change the member name, but I just want to understand why does it has this restriction, and what are my workarounds.
If you declare a member called A you can no longer use the type A without an explicit namespace. You need to change every occurrence of the type A to ::A.
The corrected code looks like:
class A { };
class B {
public:
::A& A() { return *a; }
private:
::A* a;
};
Fixed code on codepad:
http://codepad.org/cilF9rKm
That's because a member with the same name as the class is a constructor. However, you try to declare one with a type, which is an error. You can only define constructors the way the language wants you too (without an explicit return type).
For example, if you had a method in B that said
A x = A();
it is ambiguous whether you are calling B::A() or are constructing a new A object.