Consider this class:
struct Foo {
int bar;
Foo(){}
Foo(int a) {
bar = a;
}
};
Now, I have two ways to access member bar:
Foo foo(1234);
cout << foo.bar << endl;
cout << foo.Foo::bar << endl;
But I don't know what is foo.Foo's kind:
using namespace foo.Foo; //error, because foo.Foo is not a namespace
foo.Foo baz; //error, because foo.Foo is not a class
Please tell me what is foo.Foo.
foo.Foo isn't anything. Foo::bar is the bar member of the Foo class, and foo.Foo::bar is the bar member of the Foo class in the instance foo.
That syntax is generally used if you have name conflicts with multiple inheritance. Consider this example:
struct A{int bar;};
struct B{int bar;};
struct C:A,B{};
Now the following code is ambiguous:
C c;
std::cout << c.bar;
We need to say which bar we want:
C c;
std::cout << c.A::bar;
std::cout << c.B::bar;
It is not (foo.Foo)::bar, it's foo.(Foo::bar) and Foo::bar is bar
This can be usefull in this example :
struct A{
int i;
};
struct B{
int i;
};
class C : public A, B{
};
int main(){
C c;
c.i = 0; // request for member 'i' is ambiguous
}
you should use namespaces A and B to access the data, A::i or B::i
Members of struct are public by default , so you can access memebrs with dot and well as scope resolution (::) operator.So foo.Foo::bar is same as foo.bar.
Related
I want to keep the actual struct hidden, but provide a interface name for user.
so my code goes:
class A
{
private:
struct B{...};
public:
using BPtr = B*;
B* funct(){...};
}
my usage would be
A a;
BPtr p = a.funct();
The full name is A::BPtr, so this will work:
A::BPtr p = a.funct();
On the other hand, this is pretty pointless, as only the name "B" is private – the class definition isn't.
For example,
class A
{
private:
struct B{ int x = 1234; } b;
public:
using BPtr = B*;
B* funct(){ return &b; };
};
int main() {
A a;
A::BPtr b = a.funct();
std::cout << b->x << std::endl;
}
outputs "1234", and so does
class A
{
private:
struct B{ int x = 1234; } b;
public:
B funct(){ return b; };
};
int main() {
A a;
std::cout << a.funct().x << std::endl;
}
even though A::B b = a.funct(); would not compile (but auto b = a.funct() would).
Lesson: if you hand someone a thing, they can use it - even if they don't know what to call it.
An addition to the answer by #molbdnilo:
Note that even if you don't expose the struct pointer as BPtr, it's not private anymore once you're returning it outside the class.
Here is an example of using the struct outside of the class:
#include <iostream>
#include <type_traits>
class A
{
private:
struct B { int num; };
public:
B* funct() { return new B {}; }
};
int main()
{
A a;
typedef std::remove_reference_t<decltype(*a.funct())> B;
B b { 3 };
std::cout << b.num << std::endl;
}
I have a class B with a pointer attribute of class A with a method that assigns the pointer attribute to the variable of the other class A. Yet this variable is private, assigning the variable therefore create an error. How can I solve this issue?
#include<iostream>
using namespace std;
class A {
private :
int x;
public:
A(int);
~A();
};
class B {
private :
A * pA;
int y;
public:
B(int, int);
~B();
void imprimer();
};
void B::imprimer() {
cout << "B::imprimer: " << pA->x << " " << y << endl;
}
main()
{
B to(1, 2);
to.imprimer(); //instruction (1)
}
Gives the following result :
$ g++ td4Exercice1_2.cpp -o td4Exercice1_2
td4Exercice1_2.cpp: In member function ‘void B::imprimer()’:
td4Exercice1_2.cpp:7:6: error: ‘int A::x’ is private
int x;
^
td4Exercice1_2.cpp:24:33: error: within this context
cout << "B::imprimer: " << pA->x << " " << y << endl;
What you are missing are the class get() and set(int) methods for class A
OR
You have not declared Class B to be a friend of Class A.
A's x is a private variable within Class A. Only Class A can modify its variables, unless you do a few things.
You declare Class B to be a friend of Class A.
class B; // you must 'declare Class B before Class A for this to work
class A {
friend class B;
private :
int x;
public:
A(int);
~A();
};
This would allow class B full access to anything in Class A. BUT this is a POOR design.
There complex ways to do this as shown in "C++ Primer", S. Lippman that allow the "<<" operators to friend the class for output. QED.
The least intrusive way to do this is to create a new method in class A.
class A {
private :
int x;
public:
A(int);
~A();
int getX( void) { return( x ) };
};
void B::imprimer() {
cout << "B::imprimer: " << pA->getX() << " " << y << endl;
}
now you can get the value of A::x without being able to change it.
This does lead to some greater design problems in that you now have the last value of A::x, though possible not the current value of A::x. x could have been modified before you begin to use the value you have for x.
Further study of using 'friend' with "<<" ">>" operators will show you a better way depending on what the big picture is for your program.
This is regarding the question
A class name introduced inside a class is not treated as a nested class name.
I am confused why Part1 and Part2 are different with respect to §3.3.2 [basic.scope.pdecl]/p7 of the standard:
Both are Elaborated Type specifiers and should fall into same section But it seems that there scope seems to be different
Part 1:
struct A
{
struct B;
B* m_b;
};
Part 2:
struct A
{
struct B* m_b;
};
Please guide me in this.
Maybe this little example will help to elaborate:
#include <iostream>
struct B {
void call() { std::cout << "B" << std::endl; }
};
struct A {
struct B* p;
};
struct A2 {
struct B;
struct B* p;
};
struct A2::B {
void call() { std::cout << "A2::B" << std::endl; }
};
int main()
{
B pb;
A2::B pb2;
auto a = A { &pb };
a.p->call();
auto a2 = A2 { &pb2 };
a2.p->call();
return 0;
}
expected results:
B
A2::B
Summary:
A::p is a B*
A2::p is a A2::B*
A2::B and B are entirely different classes
In code below:
class B {
int x;
int y;
};
class A {
friend class Other;
friend class A;
int a;
B* b;
public:
A(){ b = new B();}
};
struct Other {
A a;
void foo() {
std::cout << a.b->x; // error
}
};
int main() {
Other oth;
oth.foo();
}
The indicated line fails with:
t.cpp:22:19: error: 'x' is a private member of 'B'
std::cout << a.b->x;
^
t.cpp:7:5: note: implicitly declared private here
int x;
Why friendship is not working when referring from class member to other class member?
This line:
std::cout << a.b->x;
involves accessing a private member of A (b) and a private member of B (x) within class Other. While A gave access privileges to Other, B did not, hence the error. If you want this to work, you'll need to add:
class B {
friend class Other;
};
Side-note, this declaration is meaningless:
class A {
friend class A;
};
A class already has access to its own private members. So calling it its own friend is redundant.
Although this is a weird use of friends, I assume it is for learning purposes. That said, you should fix your friends definition like this:
class B{
friend class Other; // Because you access private member x from Other::foo()
int x;
int y;
};
class A{
friend class Other; // Because you access private member b from Other::foo()
int a;
B* b;
public:
A(){ b = new B();}
};
struct Other{
A a;
void foo(){
// Access A's private member b
// Access B's private member x
std::cout << a.b->x;
}
};
Try this:
class B{
friend class Other;
int x;
int y;
};
I'm wondering something in C++.
Admitting the following code:
int bar;
class Foo
{
public:
Foo();
private:
int bar;
};
Inside my class, is there any difference between this->bar and Foo::bar? Are there cases where one is invalid?
Inside class Foo (specifically) there is no difference between the two given that bar is not static.
Foo::bar is called the fully qualified name of the member bar, and this form is useful in scenarios where there may be several types in the hierarchy defining a member with the same name. For example, you would need to write Foo::bar here:
class Foo
{
public: Foo();
protected: int bar;
};
class Baz : public Foo
{
public: Baz();
protected: int bar;
void Test()
{
this->bar = 0; // Baz::bar
Foo::bar = 0; // the only way to refer to Foo::bar
}
};
They do the same thing members.
However, you wont be able to use this-> to distinguish members of the same name in the class hierarchy. You will need to use the ClassName:: version to do that.
For what I have learned fiddling around with C/C++, using the -> on something is mainly for a pointer object, and using :: is used for the classes that are part of a namespace or super class that is the general class of whatever you're including
It also allows you you to reference variable of another class (base class in most cases) with the same name. For me it's obvious from this example, hope it'll helps you.
#include <iostream>
using std::cout;
using std::endl;
class Base {
public:
int bar;
Base() : bar(1){}
};
class Derived : public Base {
public:
int bar;
Derived() : Base(), bar(2) {}
void Test() {
cout << "#1: " << bar << endl; // 2
cout << "#2: " << this->bar << endl; // 2
cout << "#3: " << Base::bar << endl; // 1
cout << "#4: " << this->Base::bar << endl; // 1
cout << "#5: " << this->Derived::bar << endl; // 2
}
};
int main()
{
Derived test;
test.Test();
}
This is because the real data stored in class is like this:
struct {
Base::bar = 1;
Derived::bar = 2; // The same as using bar
}