Why can't my friend function access the private members? - c++

The addBudget function in AuxiliaryOffice class is a friend function of the budget class. But the compiler is giving me error, that it cannot access the private members of the Budget class.
class Budget;
class AuxiliaryOffice
{
private:
double auxBudget;
public:
AuxiliaryOffice()
{
auxBudget = 0;
}
double getDivisionBudget()
{
return auxBudget;
}
void addBudget(double a, Budget &ref)
{
ref.corpBudget += a;
auxBudget += a;
}
};
class Budget
{
private:
static double corpBudget;
double divisionBudget;
friend void AuxiliaryOffice::addBudget(double, Budget&);
public:
Budget()
{
divisionBudget = 0;
}
void addBudget(double a)
{
corpBudget += a;
divisionBudget += a;
}
double getDivisionBudget() const
{
return divisionBudget;
}
double getCorpBudget() const
{
return corpBudget;
}
};
double Budget::corpBudget = 0;

The error you get is stopping your code from compile before friendship is even an issue.
You declared Budget as an incomplete type:
class Budget;
And then wrote code that calls functions on it, before the class is defined. That is not allowed. You have to declare functions that use it, but NOT define it until after the class is defined.
That's why (one of the reasons why) we put class declarations in headers, and implementations in .cpp files. It also reduces coupling between files, and can help with build speeds.
Here's a compacted version of your code that compiles, with most of the unessential lines removed (as you should aim to do in future questions):
class Budget;
class AuxiliaryOffice {
double auxBudget = 0;
public:
void addBudget(double a, Budget &ref);
};
class Budget {
// Unrelated, but useful to know:
// inline statics can be initialized in the class like this, no
// definition necessary in the .cpp file.
inline static double corpBudget = 0;
friend void AuxiliaryOffice::addBudget(double, Budget&);
};
// if in .cpp, remove "inline", if in header, keep it
inline void AuxiliaryOffice::addBudget(double a, Budget &ref) {
ref.corpBudget += a;
}
see it live: https://godbolt.org/z/JYDZMz

The problem is not about friendship, is about the order of definition. At the point you've defined AuxiliaryOffice::addBudget the definition of Budget is incomplete, hence the member corpBudget isn't defined yet.
Change it to:
class Budget;
class AuxiliaryOffice
{
private:
double auxBudget;
public:
AuxiliaryOffice()
{
auxBudget = 0;
}
double getDivisionBudget()
{
return auxBudget;
}
void addBudget(double a, Budget &ref);
};
class Budget
{
private:
static double corpBudget;
double divisionBudget;
friend void AuxiliaryOffice::addBudget(double, Budget&);
public:
Budget()
{
divisionBudget = 0;
}
void addBudget(double a)
{
corpBudget += a;
divisionBudget += a;
}
double getDivisionBudget() const
{
return divisionBudget;
}
double getCorpBudget() const
{
return corpBudget;
}
};
double Budget::corpBudget = 0;
inline void AuxiliaryOffice::addBudget(double a, Budget &ref)
{
ref.corpBudget += a;
auxBudget += a;
}
That will work.

Related

Why does my class polymorphism fail (C++)

I want to return a struct which uses a number and one object deriving from one of 3 subclasses that tell the method where to add the number. My thought process is that using runtime polymorphism, I can overload the method and have the sum of different sub classes in 3 variables. However this doesn't seem to happen because the object doesn't get casted down to it's child class. Bear in mind, that the program doesn't know beforehand which subclass will be the struct, so manual casting is not possible.
The class with the subclasses (s.h):
#pragma once
class Sugar{};
class Nincs : public Sugar
{
private:
static Nincs* ins;
Nincs(){};
public:
static Nincs* instance();
};
class Alfa : public Sugar
{
private:
static Alfa* ins;
Alfa(){};
public:
static Alfa* instance();
};
class Delta : public Sugar
{
private:
static Delta* ins;
Delta(){};
public:
static Delta* instance();
};
The class with the subclasses (s.cpp):
#include "s.h"
Nincs* Nincs::ins = nullptr;
Alfa* Alfa::ins = nullptr;
Delta* Delta::ins = nullptr;
Nincs* Nincs::instance()
{
if (ins == nullptr)
{
ins = new Nincs();
}
return ins;
};
Alfa* Alfa::instance()
{
if (ins == nullptr)
{
ins = new Alfa();
}
return ins;
}
Delta* Delta::instance()
{
if (ins == nullptr)
{
ins = new Delta();
}
return ins;
}
The classes that return the struct (this is only n.h for now, I plan to separate it into .h and .cpp once this issue is resolved):
#pragma once
#include "s.h"
struct Sugarzas
{
Sugar* fajta;
int mennyiseg;
};
class Noveny
{
protected:
std::string nev;
int tapanyag;
bool el_e;
public:
Noveny(std::string v1, int v2, bool v3): nev(v1), tapanyag(v2), el_e(v3){}
virtual Sugarzas ker(){};
};
class Puffancs : public Noveny
{
public:
Puffancs(std::string v1, int v2, bool v3): Noveny(v1,v2,v3){};
Sugarzas ker() override
{
Sugarzas s;
s.fajta = Alfa::instance();
s.mennyiseg = 10;
return s;
}
};
class Deltafa : public Noveny
{
public:
Deltafa(std::string v1, int v2, bool v3): Noveny(v1,v2,v3){};
Sugarzas ker() override
{
Sugarzas s;
s.fajta = Delta::instance();
if (tapanyag < 5)
{
s.mennyiseg = 4;
}
else if (tapanyag >=5 && tapanyag <=10)
{
s.mennyiseg = 1;
}
else
{
s.mennyiseg = 0;
}
return s;
}
};
class Parabokor : public Noveny
{
public:
Parabokor(std::string v1, int v2, bool v3): Noveny(v1,v2,v3){};
Sugarzas ker() override{}
};
main file with the functions:
#include <iostream>
#include "s.h"
#include "n.h"
using namespace std;
int sumNincs, sumAlfa, sumDelta;
void addTo(Nincs* s, int x)
{
sumNincs += x;
}
void addTo(Alfa* s, int x)
{
sumAlfa += x;
}
void addTo(Delta* s, int x)
{
sumDelta += x;
}
int main()
{
Puffancs* n = new Puffancs("bob",5,true);
sumNincs = 0;
sumAlfa = 0;
sumDelta = 0;
Sugarzas s = n->ker();
addTo(s.fajta,s.mennyiseg); //s.fajta comes out as Sugar* and does not get casted to the subclasses
return 0;
}
It looks like there's some confusion between function overloading and function overriding. Virtual functions can be overridden, where a member function defined in a base class can be overridden by a member function with the same signature* in a derived class, and then calls to the base class method will be dispatched based on the actual runtime most derived class of the object the methods are being called on.
*Except possibly having a covariant return type.
However, your addTo functions are not a case of overriding. They are a case of overloading, where you have functions with the same name but different signatures. Overload resolution must be resolved at compile time. The static type of s.fajta is Sugar*, even though the actual pointed-to object is an Alfa.
You'd need your Sugar class to have virtual methods if you want to be able to have behavior that depends on the concrete type of *s.fajta. Since I'm not clear on what exactly is supposed to be happening here, I'm not sure how to restructure your program to use this behavior.

c ++ - friendship implemetation with method or common function two files

when I have two .h classes where you have to implement your methods into two corresponding cpps classes.
as it happens in the same file when I have:
class test
{
int a;
int b;
public:
friend int sum ();
};
int sum ()
{
test t;
t.a = 1;
t.b = 2;
return t.a+t.b;
}
if one of the classes declares friendship with the other, will it be implemented as a normal method?
or will it also need to be implemented as a common function?
There is just one class in this example.
The friend keyword in this example just declares that the external function (in this case sum) is allowed to access private attributes/methods of the class that it has friendship with.
It is a normal function, not a method, thus something like this: test::sum() or test t; t.sum() is not possible.
If you want to access private attributes/methods from this class with another class it works like the following:
#include <iostream>
class Test2;
class Test1 {
int a;
int b;
public:
Test1(int a, int b) : a(a), b(b) {}
int sum(const Test2& t) const;
};
class Test2 {
int c;
public:
Test2(int c) : c(c) {}
friend int Test1::sum(const Test2& t) const;
};
int Test1::sum(const Test2& t) const { return a + b + t.c; }
int main()
{
Test1 t1(2, 4);
Test2 t2(3);
std::cout << t1.sum(t2) << std::endl;
return 0;
}
For more and more specific information of the friend keyword take a look here:
https://en.cppreference.com/w/cpp/language/friend

Constructor move

I have a code:
#include "stdafx.h"
#include "memory"
#include <gtest\gtest.h>
class Money
{
public:
explicit Money(int value) :value(value) {} ;
Money(Money&& m) :value(m.returnValue()) {};
Money(const Money &m) = default;
Money operator-(const Money &m) ;
Money &operator=(Money &&m) { return Money(m.returnValue()); };
Money &operator=(const Money &m)=default;
int returnValue() const { return value; };
~Money() = default;
private:
int value;
};
Money Money::operator-(const Money &m)
{
return Money(value - m.returnValue());
}
class Bank {
public:
Bank(Money m) :propertiesBank(std::make_unique<PropertiesBank>(std::move(m))) {};
int returnMoney() const { return propertiesBank->money->returnValue(); }
~Bank() = default;
private:
struct PropertiesBank;
std::unique_ptr<PropertiesBank> propertiesBank;
};
struct Bank::PropertiesBank
{
std::shared_ptr<Money> money;
PropertiesBank(Money&& m) :money(std::make_shared<Money>(m)) {};
};
int main()
{
Money k(1000);
Bank bank(k);
return 0;
}
I want display(returnMoney()) money in the Bank, but I can't. I could make class with struct Impl and unique_ptr for training.
I know, that unique can't copy.
How can I make this programm?
Are the rest of my code is well?
Error
Error C2027 use of undefined type 'Bank::PropertiesBank' Error
C2039 'returnValue': is not a member of 'std::unique_ptr>'
The only issue I can see is that the definition of Bank::returnMoney tries to access Bank::PropertiesBank when it has only been forward-declared, not defined. Moving PropertiesBank to be defined incline within Bank fixes this.
However as Mooing Duck points out in the comments, if your intention is to implement the pImpl idiom, then both Bank::PropertiesBank and Bank::returnMoney should be defined in a .cpp file, rather than within the class definition.
#include <memory>
class Money
{
public:
explicit Money(int value) :value(value) {} ;
Money(Money&& m) :value(m.returnValue()) {};
Money(const Money &m) = default;
Money operator-(const Money &m) ;
Money operator==(Money &&m) { return Money(m.returnValue()); };
int returnValue() const { return value; };
~Money() = default;
private:
int value;
};
Money Money::operator-(const Money &m)
{
return Money(value - m.returnValue());
}
class Bank {
public:
Bank(Money m) :propertiesBank(std::make_unique<PropertiesBank>(std::move(m))) {};
int returnMoney() const { return propertiesBank->money->returnValue(); }
~Bank() = default;
private:
struct PropertiesBank
{
std::shared_ptr<Money> money;
int returnMoney() const { return money->returnValue(); }
PropertiesBank(Money&& m) :money(std::make_shared<Money>(m)) {};
};
std::unique_ptr<PropertiesBank> propertiesBank;
};
#include <iostream>
int main()
{
Money m(10);
Bank b(m);
std::cout << b.returnMoney();
return 0;
}
Its not a problem with std::unique_ptr, its the fact that you tried accessing a member of an object whose type is PropertiesBank when the compiler hasn't seen its full definition. You should move the definition of the member function outside the class and at the point where the compiler has seen the full definition of PropertiesBank:
See the comment in this snippet below:
class Bank {
public:
Bank(Money m) :propertiesBank(std::make_unique<PropertiesBank>(std::move(m))) {};
int returnMoney() const;{ return propertiesBank->money->returnValue(); }
// .......The compiler doesn't know that `money`^^^^^^ belongs to `PropertiesBank`
~Bank() = default;
private:
struct PropertiesBank;
std::unique_ptr<PropertiesBank> propertiesBank;
};
struct Bank::PropertiesBank
{
std::shared_ptr<Money> money;
PropertiesBank(Money&& m) :money(std::make_shared<Money>(m)) {};
};
You should move the function's definition to after where the compiler has seen the definition of the type of propertiesBank:
class Bank {
public:
Bank(Money m) :propertiesBank(std::make_unique<PropertiesBank>(std::move(m))) {};
int returnMoney() const; //member function declaration
~Bank() = default;
private:
struct PropertiesBank;
std::unique_ptr<PropertiesBank> propertiesBank;
};
struct Bank::PropertiesBank
{
std::shared_ptr<Money> money;
PropertiesBank(Money&& m) :money(std::make_shared<Money>(m)) {};
};
//Member function's definition
int Bank::returnMoney() const { return propertiesBank->money->returnValue(); }

Getting one private member from one class to another

So, I have an algorithm that takes a few sensors, scales them to a temperature and puts the temps in a global data store. However, sensor class A does more calculations that Class B needs. I can't put the new calcs in the data store, and i don't want to include class A inside class B just to get one piece of data with a getter.
Class A
{
private:
float x[4];
float y[4];
public:
//Scaling functions, etc...
}
Class B
{
private:
float c[4];
public:
//Scaling functions etc...
}
What would be the best way to get x[4] passed to class B to put in c[4]? The real classes have much more going on, this is about as simple as I think I can make. x[4] has data that needs to be used in class B.
class A
{
private:
float x[4];
float y[4];
public:
float* getXs()
{
return x;
}
}
class B
{
private:
float c[4];
public:
//Scaling functions etc...
void setXs(float *x)
{
for (int i=0;i<4;i++)
c[i] = x[i];
}
}
Well, you could use friends, if you're not willing to write accessors:
http://en.wikipedia.org/wiki/Friend_class
Some would argue this breaks encapsulation, and that a getter would be the preferred approach.
Use a getter of x[4] on an instance of A when calling the constructor of B.
#include <string.h>
class A
{
private:
float x[4];
float y[4];
public:
float const *xArray() const
{
return x;
}
};
class B
{
private:
float c[4];
public:
void setCArray(float const arr[4])
{
memcpy(c, arr, 4 * sizeof(int));
}
};
int main()
{
A a;
B b;
b.setCArray(a.xArray());
}
There are number of ways. The best depends on Your criteria.
If time is not crucial for you I would be simple and use copy constructor:
Class A
{
private:
float x[4];
float y[4];
public:
const float& X(int i) { return x[i]; }
}
Class B
{
private:
float c[4];
public:
B( const A& a ) {
for( k = 0; k < 4; k++ )
c[k] = a.X(k);
}
}
If time is crucial you can consider to use pointers copy. But be Very accurate with it:
Class A
{
private:
friend B;
float x[4];
float y[4];
public:
...
}
Class B
{
private:
const float* const c;
public:
B( const A& a ):c(a.x){}
// use c like c[4], but don't change it.
}

Friend Function calling Static Members of Derived Classes. Not getting expected output

My first post here :)
I am having a problem with the following C++ code. I have an ABC class A, and two derived classes B and C. All of them have a static member called id:
using std::cout;
class A
{
private:
friend int bar(A& a);
static const int id = 1;
virtual void foo() = 0;
};
class B : public A
{
private :
friend int bar(A& a);
static const int id = 2;
void foo() { /*Do something*/ }
};
class C : public A
{
private:
friend int bar(A& a);
static const int id = 3;
void foo() { /*Do something*/ }
};
int bar(A& a)
{
return a.id;
}
int main()
{
B b;
C c;
cout << bar(b) << "\n";
cout << bar(c) << "\n";
return 0;
}
I was expecting this code to print out 2 and 3 - rather it prints out 1 and 1 (bar() is always using A::id). What am I doing wrong? Any ideas?
Based on the comments below, this the final code I am using. It works, but would love to hear more thoughts :)
#include <iostream>
using std::cout;
class A
{
private:
virtual void foo() = 0;
};
class B : public A
{
private:
template <typename T>
friend int bar(T& t);
static const int id = 2;
void foo() { /*do something*/ }
};
class C : public A
{
private:
template <typename T>
friend int bar(T& t);
static const int id = 3;
void foo() { /*do something*/ }
};
template <typename T>
int bar(T& t)
{
return t.id;
}
int main()
{
B b;
C c;
cout << bar(b) << "\n";
cout << bar(c) << "\n";
return 0;
}
a.id will be defined at compile-time as A::id. You would need to define a virtual member (non-static) function in class A and have it overridden in B and C to return their respective ids and call this function in bar.
Is there any way to avoid writing int foo() { return id; } for all the derived classes?
Yes, using templates. For example:
template <typename T>
int foo (T& x)
{
return x.id;
}
However, if id is private, this doesn't reduce the code by all that much.