I am writing code to access private members of a class through another friend class. The below code works
// Example program
#include <iostream>
#include <string>
using namespace std;
class Foo
{
private:
int a;
protected:
public:
friend class Bar;
Foo(int x)
{
a = x ;
}
};
class Bar
{
private:
protected:
public:
int b;
Bar(Foo& f)
{
b = f.a;
cout << "f.a is " << f.a << endl;
}
};
int main()
{
Foo foo(5);
Bar bar(foo);
cout << "Value of variable b is " << bar.b << endl;
}
Above code works fine. However, if I want to access a private variable of Foo through a function in friend class Bar, I am unable to. See code below
#include <iostream>
#include <string>
using namespace std;
class Foo
{
private:
int a;
protected:
public:
friend class Bar;
Foo(int x)
{
a = x ;
}
};
class Bar
{
private:
protected:
public:
int b;
Bar(Foo& f)
{
b = f.a;
}
void printvariable(void)
{
cout << "f.a is " << f.a << endl;
}
};
int main()
{
Foo foo(5);
Bar bar(foo);
cout << "Value of variable b is " << bar.b << endl;
}
I totally understand why execution fails on the
void printvariable(void)
{
cout << "f.a is " << f.a << endl;
}
function since f is not in scope for the function. However, since I am passing Foo f in the constructor for Bar b, I am hoping to write code that will allow me to access members in Foo without passing Foo f to the function printvariable() again.
What is the most efficient way to write this code?
You can keep the reference to f. The code should be:
class Bar
{
private:
protected:
public:
int b;
Foo& f_ref;
Bar(Foo& f)
:f_ref(f)
{
b = f.a;
}
void printvariable(void)
{
cout << "f.a is " << f_ref.a << endl;
}
};
TEST!
You can do it like this, but if I were you I'd write some getters, also – class friendship isn't really recommended.
class Bar {
public:
Foo& ref;
Bar(Foo& f)
: ref { f }
{ }
void printvariable() {
cout << "f.a is " << ref.a << endl;
}
};
Btw there's no reason to add void in brackets in C++, it lost its meaning from C and has no effect by now.
You are wrong in one point. You are indeed passing a reference to f in the ctor, but the constructor and whole class Bar does not remember a whole object of f. In your original code, the constructor only makes the Bar object remember the int a part of the object, so only that little bit is later accessible:
class Foo
{
...
friend class Bar;
...
};
class Bar
{
...
int b;
Bar(Foo& f)
{
b = f.a; // <=--- HERE
}
void printvariable(void)
{
cout << "f.a is " << b << endl; // <-- now it refers B
}
Please note how your ctor of Bar only reads f.a and stores it in b. From now on, the Bar object only remembers b and that's all. You can freely access the b in printvariable. However, it will not be the a-taken-from-f. It will be b, that was set to the same value as f.a during constructor. Since that point of time, b and f.a are totally separate. That's how value copying works.
To make Bar remember whole f, you have to, well, remember whole f:
class Bar
{
...
Foo wholeThing;
Bar(Foo& f)
{
wholeThing = f; // <=--- HERE
}
void printvariable(void)
{
cout << "f.a is " << wholeThing.a << endl;
}
However, again, there's a catch: now since wholeThing is of type Foo, the constructor will actually make a copy of that object during wholeThing=f. Just the same as it was when b=f.a, but now it remembers a copy of whole f.
Of course, it's only matter of type. You can store a reference instead of whole-Foo, but it needs a bit different initialization syntax:
class Bar
{
...
Foo& wholeThing;
Bar(Foo& f) :
wholeThing(f) // <=--- HERE
{
// <=--- empty
}
void printvariable(void)
{
cout << "f.a is " << wholeThing.a << endl;
}
Related
I wanted to know if there's any exsisting solution to the problem:
class b;
class a {
int x;
public:
friend class b;
a() { x = 5 }
void print(b obj) {
cout << x << endl;
cout << obj.y << endl;
}
};
class b {
int y;
public:
friend class a;
b() { y = 10 }
void print(a obj) {
cout << y << endl;
cout << obj.x << endl;
}
};
"This is giving me an issue since class b body is not define before class a, so what is there any easy and existing way to make it work?
For starters you forgot to place a semicolon after these statements
x = 5
and
y = 10
You can define member functions that access data members of other class when the other class is defined that is when it is a complete type.
So place the definition of the function print of the class a after the definition of the class b.
For example
#include <iostream>
using namespace std;
class b;
class a {
int x;
public:
friend class b;
a() { x = 5; }
/* inline */ void print(b obj);
};
class b {
int y;
public:
friend class a;
b() { y = 10; }
void print(a obj) {
cout << y << endl;
cout << obj.x << endl;
}
};
void a::print(b obj) {
cout << x << endl;
cout << obj.y << endl;
}
int main()
{
a a;
a.print( b() );
b b;
b.print( ::a() );
return 0;
}
The program output is
5
10
10
5
You could place the class definitions with member function declarations in a header and then define the member functions in a cpp file.
I am learning C++14, in that come across this template variable feature and that interested me to dig more on this and i tried with multiple examples to understand the template variables. Say,
template <typename T>
T var;
var<int>;
var<float>;
Above code worked and it looked straight forward to understand too. But, when I tried to use class name in place of int or float as shown above, result in calling the temporary object creation for the class FOO and calling corresponding C'tor & dtor for the temp object.
var<FOO>; //FOO is a class
I have written a sample test program and its output for your understanding. My question is that,
Why var creates temp object?
How template variable differ for primitive datatypes and user defined datatypes?
If it is irrelevant or duplicate, please point me to the source for clear understanding.
Refer code below,
class B
{
public:
B()
{
std::cout<<"\nB ctor"<<std::endl;
}
B(const B& obj)
{
std::cout<<"B copy ctor"<<std::endl;
}
int operator()()
{
std::cout<<"operator() called"<<std::endl;
}
void f() {
//::A().print();
}
~B()
{
std::cout<<"\n~ for B()"<<std::endl;
}
};
//Declaring template variable
template<typename T>
T g ;
int main() {
g<int> = 30;
g<float> = 30.02f;
g<B> = B{};
std::cout<<"g value:"<<g<int><<std::endl;
std::cout<<"g value:"<<g<float>;
}
Output:
B ctor
g value:30
g value:30.02
~ for B()
No temporary object is created by this simple program:
int main() {
var<SomeClass>;
}
A temporary object is created here:
int main() {
var<SomeClass> = SomeClass{};
}
but that is because we did it with SomeClass{}. We then assigned that to the var<SomeClass> non-temporary object (global in many of your examples).
The code that runs here is
SomeClass::SomeClass()
SomeClass::SomeClass()
SomeClass::operator=(SomeClass&&)
SomeClass::~SomeClass()
SomeClass::~SomeClass()
in that order.
#include <iostream>
struct noisy {
noisy() { std::cout << __func__ << "()\n"; }
~noisy() { std::cout << __func__ << "()\n"; }
noisy(noisy&&) { std::cout << __func__ << "(&&)\n"; }
noisy(noisy const&) { std::cout << __func__ << "(c&)\n"; }
void operator=(noisy&&) { std::cout << __func__ << "(&&)\n"; }
void operator=(noisy const&) { std::cout << __func__ << "(c&)\n"; }
};
template<class T>
T var;
int main() {
std::cout << "Start of main\n";
{
var<noisy> = noisy{};
std::cout << "Body of main\n";
}
std::cout << "End of main\n";
}
live example.
Output:
noisy()
Start of main
noisy()
operator=(&&)
~noisy()
Body of main
End of main
~noisy()
The private data member is inaccessible. Although i have declared function as friend of class.
Can anyone help me.
class ONE;
class TWO {
public:
void print(ONE& x);
};
class ONE {
private:
int a, b;
public:
friend void TWO::print(ONE& x);
ONE() : a(1), b(2) { }
};
void TWO::print(ONE& x) {
cout << "a is " << x.a << endl;
cout << "b is " << x.b << endl;
}
int main() {
ONE xobj;
TWO yobj;
yobj.print(xobj);
}
Error Picture is attached.
As far as I know in C++ we cannot use the same identifier for another declaration:
int x;
char x; // compile-time error: redefinition.
But here is an example where I was messing with classes:
#include "stdafx.h"
#include <iostream>
#include <vector>
class A {
public:
A(int);
void print()const;
friend std::ostream& operator << (std::ostream& out, A& rhs);
private:
int value1;
};
std::ostream& operator << (std::ostream& out, A& rhs) {
out << "rhs.value1 = " << rhs.value1 << std::endl;
return out;
}
A::A(int x) : value1(x) { std::cout << "ctor A(x)" << std::endl; }
void A::print()const {
std::cout << "value1: " << value1 << std::endl;
}
int A(int x) {
std::cout << "inside A(int x)" << std::endl;
return x;
}
int main(){
class A a { 0 };
a = A(7);
a.print();
std::cout << A(7) << std::endl;
std::cout << A(5) << std::endl; // here if I comment out the function a it is ok as long as I overloaded the insertion operator
// and if I add the function A it hides the insertion operator!
std::cout << std::endl;
std::cin.get();
return 0;
}
So as you can see above I must add the keyword class whenever I declare an object of class Aotherwise I get a compile-time error. Why?
Is the expression a = A(7); a function call and the return value is passed to the constructor of class A that takes an integer. Or simply no function call but only ctor call?
From my point of view, you have a class A and a function A, so you have to point out A is a class or a function that's why you have to add "class" when you declare an object of A.
According to the following code, two classes, A and B, are defined, they are exactly same, but A can be a function or a class, so when you declare a object A, you have to add a "class" before A, while declare a object of B is no need to add a "class"
For the second question, first function A is called, and its return value is used to construct object a. You can see first x=7 is in the function A, and ctor x=8 because the function return x+1.
The output:
ctor A(x) x=0
inside A(int x) x=7
ctor A(x) x=8
ctor B(x)
The test code:
#include <iostream>
#include <vector>
class A {
public:
A(int);
private:
int value1;
};
class B {
public:
B(int);
private:
int value1;
};
B::B(int x) : value1(x) { std::cout << "ctor B(x)" << std::endl; }
A::A(int x) : value1(x) { std::cout << "ctor A(x) x=" << x <<std::endl; }
int A(int x) {
std::cout << "inside A(int x) x=" << x << std::endl;
x=x+1;
return x;
}
int main(){
class A a(0);
a = A(7);
B b(0);
return 0;
}
I'd like to call a few methods of classes 'A' and 'B' from the class 'Caller'. I need to use a function pointer because I want to call different methods.
My method gets called, but when I try to access a member variable from it, my program crashes ('program.exe has stopped working').
How come that happens?
#include <iostream>
using namespace std;
template <class T>
class Caller
{
typedef void (T::*myFunc)(int);
public:
Caller(T* obj, myFunc fp)
{
f = fp;
}
void invoke(int foobar)
{
(o->*f)(foobar);
}
private:
myFunc f;
T* o;
};
class A
{
public:
A() : n(0) {}
void foo(int bar)
{
cout << "A::foo called (bar = " << bar << ", n = " << n << ")" << endl; // the crash occurs here, and 'this' equals 0 at this point
}
void setNum(int num)
{
n = num;
}
private:
int n;
};
class B
{
public:
B() : n(0) {}
void fooo(int bar)
{
cout << "B::fooo called (bar = " << bar << ", n = " << n << ")" << endl; // same here if I call B::fooo first
}
void setNum(int num)
{
n = num;
}
private:
int n;
};
int main()
{
A myA;
B myB;
myA.setNum(128);
myB.setNum(256);
Caller<A> cA(&myA, &A::foo);
Caller<B> cB(&myB, &B::fooo);
cA.invoke(10);
cB.invoke(20);
return 0;
}
Thank you in advance.
EDIT : I use VS2017 and I can build my program without getting any compiler errors.
My method gets called, but when I try to access a member variable from it, my program crashes ...
Because you forgot to assign passed obj to o pointer in your Caller:
template <class T>
class Caller
{
typedef void (T::*myFunc)(int);
public:
Caller(T* obj, myFunc fp)
{
o = obj; // << == you need this!
f = fp;
}
void invoke(int foobar)
{
(o->*f)(foobar);
}
private:
myFunc f;
T* o;
};
Also, in general it's better to use member initializer lists:
Caller::Caller(T* obj, myFunc fp) : o(obj), f(fp)
{
}