I am a beginner in C++. I am learning the topic friend functions. I have the code below in which two friend functions are declared in the class and called by the constructor but an error shows that the declared friend member functions are not declared in the scope. What am I doing wrong here? here is my code:
#include <iostream.h>
class Salary
{
private:
int sal[10];
public:
friend void add_details();
void display();
friend void display_des();
Salary()
{
add_details();
}
};
void add_details()
{
int loop = 0;
for(loop=0;loop<10;loop++)
{
cin >> sal[loop];
if (sal[loop] <= 0)
{
cout << "The amount should be greater than 0" << endl;
loop = loop - 1;
continue;
}
}
}
void display_des()
{
int sal_des[10];
int loop1 = 0, loop2;
for(loop1=0; loop1<10; loop1++)
{
sal_des[loop1] = sal[loop1];
}
for (loop1=0; loop1<10; loop1++)
{
for(loop2=loop1+1; loop2<10; loop2++)
{
if (sal_des[loop1]< sal_des[loop2])
{
int temp;
temp = sal_des[loop1];
sal_des[loop1] = sal_des[loop2];
sal_des[loop2] = temp;
}
}
}
for(loop1=0; loop1<10; loop1++)
{
cout << sal_des[loop1];
}
}
int main()
{
Salary sal1;
sal1.display_des();
return 0;
}
Also, another error inside function display_des() is shown as sal is not declared in this scope
You are defining a global function
void display_des();
instead of the member function
void Salary::display_des();
That means display_des has no "this"- Salary-object from which it could take the member sal[]. You also don't pass it a Salary-object from outside, so which sal[] should it use?
So either you use a friend function like this:
void display_des(Salary& obj){
obj.sal[...]...
}
Or you use a member-function, similar to this:
class Salary
{
private:
int sal[10];
public:
(...)
void display_des();
(...)
};
(...)
void Salary::display_des(){
sal[...]...
(...)
}
Related
I'm trying to create a Monopoly game in C++ and I've been messing with object-oriented-programming, the problem happens with the classes "Game" and "Player", I would like to know how to use "Game"'s functions inside "Player" and "Player"'s functions inside "Game", but I've been getting a compiler error saying that the class is not defined.
Switching class positions won't work (obviously) but I tried anyways.
Code (reduced and minimized to the Game and Player classes):
namespace Monopoly {
typedef enum { normal, train, company, incometax, luxurytax, start, chancecard, chestcard, jail } type;
class Game {
private:
bool running = false;
int turn = 1;
int currentPlayerID;
int startingMoney = 1000;
std::vector<Player> players;
public:
// Functions
void createPlayer() {
++currentPlayerID;
Player newPlayer(currentPlayerID, startingMoney);
players.push_back(newPlayer);
++currentPlayerID;
}
void createPlayers(int playerAmount) {
for (int i = 0; i <= playerAmount; ++i) {
createPlayer();
}
}
Player getPlayer(int index) {
Player p = players[index];
return p;
}
};
class Player {
private:
int playerID;
int money;
std::vector<int> propertiesOwned;
void addProperty(int id) {
this->propertiesOwned.push_back(id);
}
public:
// Constructor
Player(int pID, int sMoney) {
this->playerID = pID;
this->money = sMoney;
}
// Functions
Player payMoney(int payAmount, unsigned int destinationID, Game engine) {
this->money -= payAmount;
if (destinationID > 0) {
// Checks if you're paying to a player or bank
bool playerFound = false;
for (int i = 0; i <= engine.getPlayerAmount(); ++i) {
if (engine.getPlayer(i).getID() == destinationID) {
playerFound = true;
break;
}
}
if (playerFound) {
// Player was found
engine.getPlayer(destinationID).giveMoney(payAmount);
return;
}
else {
std::cout << "\nERROR: Invalid player ID at function payMoney\n";
return;
}
}
else {
// You're paying to the bank
}
return;
}
void buyProperty(int id, int price, Game engine) {
payMoney(price, 0, engine);
addProperty(id);
}
void giveMoney(int payMoney) {
this->money += payMoney;
}
// Returns
inline int getMoney() { return this->money; }
inline int getID() { return this->playerID; }
inline auto getProperties(int index) {
auto p = propertiesOwned[index];
return p;
}
inline int getPropertyAmount() {
int amount = std::size(propertiesOwned);
return amount;
}
};
}
I expected the classes to run the other classes function normally, but it seens like that in C++, classes are defined in certain order, and you can only access classes (in a class) declared before the class you're using, feedback and alternatives that fix this would help
You are correct that in C++ declaration order matters, and that is the cause of your errors, however there are a few other issues with the code.
Firstly, you should swap the order that Game and Player are defined. This will make it easier, as Player relies on Game fewer times than Game relies on Player.
Next, add a forward declaration for Game before the definition of Player:
class Game;
This tells the compiler that a class named Game exists and allows you to use it in scenarios where it doesn't need to know the contents (i.e. definition) of the class.
Next, make payMoney and buyProperty accept their engine parameter by reference instead of by value by changing the parameter specifier to Game &engine. This is important for two reasons. First, passing by value can only be done if you have already defined the type, which we have not (we've only declared it). Second, passing by value creates a copy of the object, which in this case means a completely new vector of completely new Player objects, and the changes will not synchronize back to the old object. See here for a better explanation of references.
Next, you need to extract the definition of payMoney to after the definition of Game. The reason is that while the parameter list of payMoney no longer relies on the definition of Game, the code in the function body does (because it calls functions on the engine object). See the end for what this looks like.
This fixes all the problems with declaration/definition order. You also should make payMoney return void as its return value is never provided and never used, pick a consistent type for IDs (either int or unsigned int, not a mix), and add the getPlayerAmount to Game.
Here's what the final code could look like:
namespace Monopoly {
typedef enum { normal, train, company, incometax, luxurytax, start, chancecard, chestcard, jail } type;
class Game;
class Player {
private:
int playerID;
int money;
std::vector<int> propertiesOwned;
void addProperty(int id) {
this->propertiesOwned.push_back(id);
}
public:
// Constructor
Player(int pID, int sMoney) {
this->playerID = pID;
this->money = sMoney;
}
// Functions
void payMoney(int payAmount, int destinationID, Game &engine);
void buyProperty(int id, int price, Game &engine) {
payMoney(price, 0, engine);
addProperty(id);
}
void giveMoney(int payMoney) {
this->money += payMoney;
}
// Returns
inline int getMoney() { return this->money; }
inline int getID() { return this->playerID; }
inline auto getProperties(int index) {
auto p = propertiesOwned[index];
return p;
}
inline int getPropertyAmount() {
int amount = std::size(propertiesOwned);
return amount;
}
};
class Game {
private:
bool running = false;
int turn = 1;
int currentPlayerID;
int startingMoney = 1000;
std::vector<Player> players;
public:
// Functions
void createPlayer() {
++currentPlayerID;
Player newPlayer(currentPlayerID, startingMoney);
players.push_back(newPlayer);
++currentPlayerID;
}
void createPlayers(int playerAmount) {
for (int i = 0; i <= playerAmount; ++i) {
createPlayer();
}
}
Player getPlayer(int index) {
Player p = players[index];
return p;
}
int getPlayerAmount() {
int amount = players.size();
return amount;
}
};
void Player::payMoney(int payAmount, int destinationID, Game &engine) {
this->money -= payAmount;
if (destinationID > 0) {
// Checks if you're paying to a player or bank
bool playerFound = false;
for (int i = 0; i <= engine.getPlayerAmount(); ++i) {
if (engine.getPlayer(i).getID() == destinationID) {
playerFound = true;
break;
}
}
if (playerFound) {
// Player was found
engine.getPlayer(destinationID).giveMoney(payAmount);
return;
}
else {
std::cout << "\nERROR: Invalid player ID at function payMoney\n";
return;
}
}
else {
// You're paying to the bank
}
return;
}
}
Side note: it's technically better C++ to use size_t instead of int for variables storing the size of vectors, as that is what the size functions return (and it's an unsigned integer type whereas int is signed), but that's not especially important.
I am trying to create a class/struct that can take in a struct/class of different types that all have the function update().
I want to get the update() function and then put it in a vector as a pointer and then call it later, but I'm having trouble putting member function pointers into a vector, but I am having no problem putting 'classless' function pointers into the vector.
How can I put the member function pointers into the vector?
Here is my code
#include <vector>
#include <iostream>
#include <stdio.h>
using namespace std;
struct typeA
{
public:
int data = 0;
void update()
{
cout << "hello, my data is " << data << endl;
}
};
struct typeB
{
float data = 0;
void update()
{
cout << "hi, my data is " << data << endl;
}
};
class typeListTwo
{
typedef void(*updaterFunc)();
vector <updaterFunc> items;
public:
typeListTwo()
{
}
~typeListTwo()
{
items.~vector();
}
void addItem(updaterFunc newItem)
{
items.push_back(newItem); //This works
}
void doWork()
{
for (unsigned int funcIndex = 0; funcIndex < items.size(); funcIndex++)
{
items[funcIndex]();
}
}
};
class typeList
{
typedef void(*updaterFunc)();
vector <updaterFunc> items;
public:
typeList()
{
}
~typeList()
{
items.~vector();
}
template <class Item>
void addItem(Item newItem)
{
items.push_back(newItem.update); //But this does not?
//newItem.update(); //This also works by itself
}
void doWork()
{
for (unsigned int funcIndex = 0; funcIndex < items.size(); funcIndex++)
{
items[funcIndex]();
}
}
};
void aFunc()
{
cout << "123 hello" << endl;
}
void bFunc()
{
cout << "456 goodbye" << endl;
}
int main()
{
typeA aThing;
typeB bThing;
typeList listThings;
typeListTwo listThingsTwo;
aThing.data = 128;
bThing.data = -3.234;
listThings.addItem(aThing);
listThings.addItem(bThing);
listThings.doWork();
listThingsTwo.addItem(aFunc);
listThingsTwo.addItem(bFunc);
listThingsTwo.doWork();
return 0;
}
The way to go is to use std::function or use interface:
class typeList
{
std::vector<std::function<void()>> items;
public:
template <class Item>
void addItem(Item& item)
{
// Care: life time of item should be bigger than this instance
items.push_back([&](){ item.update(); });
}
void doWork()
{
for (auto& f : items)
{
f();
}
}
};
I am having trouble in initializing an array of structures with a function pointer as a member in it.
class Record
{
private:
typedef void (*display_fn_t) ();
struct record {
int a;
display_fn_t disp;
};
static const record rec[];
void disp1() { cout << "Display 1 with a string to display" << endl; }
void disp2() { cout << "Display 2 with an integer to display" << endl; }
public:
int find() { /* logic to find the record comes here */ }
void display() {
for (int i = 0; i < 2; i++) {
rec[i].disp();
}
}
}
const Record::record Record::rec[] = {
{ 10, disp1 },
{ 11, disp2 }
};
int main()
{
Record r;
if (r.find())
r.display();
return 0;
}
When I compile the above code, I am getting the following compilation error:
mca_record.cpp:56: error: argument of type ‘void (Record::)()’ does
not match ‘void (*)()’
Your syntax is wrong and isn't using the appropriate operators.
Fixing a multitude of syntax errors, and stripping out the unrelated find operation, then utilizing proper member function pointers and operator ->* gives the following (one of several ways to do this):
#include <iostream>
class Record
{
private:
typedef void (Record::*display_memfn_t)();
struct record
{
int a;
display_memfn_t disp;
};
static const record rec[];
void disp1() { std::cout << "Display 1 with a string to display" << std::endl; }
void disp2() { std::cout << "Display 2 with an integer to display" << std::endl; }
public:
void display();
};
const Record::record Record::rec[] =
{
{ 10, &Record::disp1 },
{ 11, &Record::disp2 }
};
void Record::display()
{
for (size_t i=0; i<sizeof rec/sizeof*rec; ++i)
(this->*(rec[i].disp))();
}
int main()
{
Record r;
r.display();
return 0;
}
Output
Display 1 with a string to display
Display 2 with an integer to display
Compare it to your existing code, and not in particular that pointers to member functions are not simply pointers to functions. They require different handling and generally different operators to utilize. See here for different methods of member access (both variable and function).
Best of luck.
To make the call work you must invoke it like this:
for (int i = 0; i < 2; i++) {
(*rec[i].disp)();
}
And initialize the table this way:
const Record::record Record::rec[] = {
{ 10, &Record::disp1 },
{ 11, &Record::disp2 }
};
I have a class for performing various array operations. I like to use my insert method in my populate method.
Can someone guide me on that? Here is the code:
#include <iostream>
#include <cstdlib>
using namespace std;
const int MAX=5;
class array
{
private:
int arr[MAX];
public:
void insert(int pos, int num);
void populate(int[]);
void del(int pos);
void reverse();
void display();
void search(int num);
};
void array::populate(int a[])
{
for (int i=0;i<MAX;i++)
{
arr[i]=a[i];
}
}
void array::insert(int pos, int num)
{
for (int i=MAX-1;i>=pos;i--)
{
arr[i] = arr[i-1];
arr[i]=num;
}
}
void array::del(int pos)
{
for (int i=pos;i<MAX;i++)
{
arr[pos]=arr[pos + 1];
}
}
void array::display()
{
for (int i=0;i<MAX;i++)
cout<<arr[i];
}
void array::search(int num)
{
for (int i=0;i<MAX;i++)
{
if (arr[i]==num)
{
cout<<"\n"<<num<<" found at index "<<i;
break;
}
if (i==MAX)
{
cout<<num <<" does not exist!";
}
}
}
int main()
{
array a;
for (int j=0;j<MAX;j++)
{
a.insert(j,j);
}
a.populate(a);
a.insert(2,7);
a.display();
a.search(44);
system("pause");
}
I like to use my insert method in my
populate method. Can someone guide me
on that?
That would mean that instead of the straightforward and efficient "copy from one array to another" approach, you'd call insert for each value of the input with the correct index in place of the assignment.
To call a method on the current instance, from inside a method:
insert(x, y);
//or
this->insert(x, y);
Your code also contains an error, in that you pass a wrong type to populate in main. It expect int* (a real array), not an array object.
Please elaborate your question. If you just need a good container have a look at the STL (Standard Template Library) std::vector. It's part of the C++ standard and comes with your compiler.
If you want to learn how to write a custom class, please try to be more precise in your question.
Also consider the wealth of beginner tutorials available on the net, for example:
http://www.learncpp.com/
Here is a little example on how to write a custom class with one member function calling the other and accessing a private data member (note that inside a member function you can refer to any other member directly):
#include <iostream>
class Example
{
private:
int some_private_stuff;
public:
Example();
void function_a();
void function_b();
};
Example::Example(){
some_private_stuff = 1;
}
void Example::function_a(){
std::cout << "this is function a" << std::endl;
some_private_stuff = 2;
std::cout << "changed private_stuff to " << some_private_stuff << std::endl;
}
void Example::function_b(){
std::cout << "this is function b" << std::endl;
function_a();
}
int main() {
Example e;
e.function_b();
return 0;
}
class Foo {
public:
Foo() { do_something = &Foo::func_x; }
int (Foo::*do_something)(int); // function pointer to class member function
void setFunc(bool e) { do_something = e ? &Foo::func_x : &Foo::func_y; }
private:
int func_x(int m) { return m *= 5; }
int func_y(int n) { return n *= 6; }
};
int
main()
{
Foo f;
f.setFunc(false);
return (f.*do_something)(5); // <- Not ok. Compile error.
}
How can I get this to work?
class A{
public:
typedef int (A::*method)();
method p;
A(){
p = &A::foo;
(this->*p)(); // <- trick 1, inner call
}
int foo(){
printf("foo\n");
return 0;
}
};
void main()
{
A a;
(a.*a.p)(); // <- trick 2, outer call
}
The line you want is
return (f.*f.do_something)(5);
(That compiles -- I've tried it)
"*f.do_something" refers to the pointer itself --- "f" tells us where to get the do_something value from. But we still need to give an object that will be the this pointer when we call the function. That's why we need the "f." prefix.
class A {
int var;
int var2;
public:
void setVar(int v);
int getVar();
void setVar2(int v);
int getVar2();
typedef int (A::*_fVar)();
_fVar fvar;
void setFvar(_fVar afvar) { fvar = afvar; }
void insideCall() { (this->*fvar)(); }
};
void A::setVar(int v)
{
var = v;
}
int A::getVar()
{
std::cout << "A::getVar() is called. var = " << var << std::endl;
return var;
}
void A::setVar2(int v2)
{
var2 = v2;
}
int A::getVar2()
{
std::cout << "A::getVar2() is called. var2 = " << var2 << std::endl;
return var2;
}
int main()
{
A a;
a.setVar(3);
a.setVar2(5);
// a.fvar = &A::getVar;
a.setFvar(&A::getVar);
(a.*a.fvar)();
a.setFvar(&A::getVar2);
(a.*a.fvar)();
a.setFvar(&A::getVar);
a.insideCall();
a.setFvar(&A::getVar2);
a.insideCall();
return 0;
}
I extended Nick Dandoulakis's answer. Thank you.
I added a function which set the member function pointer from outside of the class. I added another function which can be called from outside to show inner call of member function pointer.
Try (f.*do_something)(5);
#include<iostream>
using namespace std;
class A {
public:
void hello()
{
cout << "hello" << endl;
};
int x = 0;
};
void main(void)
{
//pointer
A * a = new A;
void(A::*pfun)() = &A::hello;
int A::*v1 = &A::x;
(a->*pfun)();
a->*v1 = 100;
cout << a->*v1 << endl << endl;
//-----------------------------
A b;
void(A::*fun)() = &A::hello;
int A::*v2 = &A::x;
(b.*fun)();
b.*v2 = 200;
cout << b.*v2 << endl;
}
I think calling a non static member of the class could also be done using a static member function.