I have a class called CoffeeShop and another class called user. i want to pass a function from the class CoffeeShop to the user class but i have an error, what i tried to do is
User class:
class user {
public:
function<void (string)> fun;
string name;
void order_coffee() {
fun(name);
}
};
then the coffeeshop class
class CoffeeShop {
public:
mutex mtx;
void Make_Coffee(string name) {
cout << "in queue: " << name << endl;
unique_lock<mutex> lock(mtx);
cout << "welcome,order in process, " << name << endl;
this_thread::sleep_for(chrono::seconds(4));
cout << "good bye, " << name << endl;
lock.unlock();
}
void assign() {
user a;
a.fun = CoffeeShop::Make_Coffee;
a.name = "amr kamal";
thread th1(&user::order_coffee, a);
user b;
b.fun = a.fun;
b.name = "hadeer";
thread th2(&user::order_coffee, b);
th2.join();
th1.join();
}
};
I use the function assigned to start running the function, what i want to do is to let the users use the make_coffee function and wait in the queue and it process 1 by 1, i want to be able to let the users access the function.
i use the class as following in the main
int main() {
CoffeeShop coffeeShop;
coffeeShop.assign();
}
the Error i got is on assign the user make_coffee function
error C2679: binary '=': no operator found which takes a right-hand operand of type 'void (__cdecl CoffeeShop::* )(std::string)' (or there is no acceptable conversion)
You have two options
Wrap it in a lambda a.fun = [this](string line) {this->Make_Coffee(line);};
Use std::mem_fun
The problem you are facing is that std::function needs to know about this. Also Why is "using namespace std;" considered bad practice?
Related
I have to classes, A and B. There are actually many other classes that all share a pointer to A, because A is sort of a manager that controls all the other classes during runtime.
The idea is that A and B both open a bunch of file I/Os during their lifetime, but any class can request the execution to stop. At this point, I'd like to gracefully close all the files which are open. B and all other classes all contain a member function like
void B::CloseFile()
So my idea was that I first instantiate A which contains an empty vector of CloseFile function pointers, then instantiate all the subsequent classes that "register" their own Close functions in A's vector. Then any class can call a stop, and call A's (since all classes have a pointer to A) CloseAll function, which traverses the vector and closes everything its got.
I tried to prototype this in a simple example and I'm getting stuck. Here is the code that doesn't work, the last line throws an error.
// Example program
#include <iostream>
#include <string>
using std::cout;
class B;
typedef void (B::*bfnptr)();
class A {
public:
// Some methods
void SetBfn(bfnptr new_ptr) { do_b_ = new_ptr; };
// Some vars
int a_ = 0;
bfnptr do_b_ = nullptr;
};
class B {
public:
// More methods
void ZeroMe() { b_ = 0; };
void SetA(A* obj_a) { aptr_ = obj_a; };
void IncMe(int op) { b_ += op; };
// More vars
A* aptr_ = nullptr;
int b_ = 1;
};
int main()
{
// Two instances
A obj_a;
B obj_b;
// Setup B to point to A
obj_b.SetA(&obj_a);
// Manipulate A through B
cout << "A var initially: " << obj_a.a_ << "\n";
obj_b.aptr_->a_ = 10;
cout << "A var is now: " << obj_a.a_ << "\n";
// Object b can do things
cout << "B var initially: " << obj_b.b_ << "\n";
obj_b.IncMe(1);
cout << "B var is now: " << obj_b.b_ << "\n";
// Set A to point to a function in B
obj_a.SetBfn(&obj_b::ZeroMe);
}
When I compile this with C++14, I get the error
In function 'int main()':
51:19: error: 'obj_b' is not a class, namespace, or enumeration
This is actually not my question; I'm not sure why this is happening. The actual question I wanted to ask was how to handle the circular dependency between classes A and B. But why is that error happening?
So, what i'm trying to do is this:
I would like to create a general class MyCLASS with a function genericFunction() which is empty by default. Now, when a co-worker wants to use this generic function, what he does is creating an instance of MyClass, and overriding genericFunction(), so it should give a resoult similar to this:
class MyClass{
public:
void genericFunction(){
//boring default actions
}
//constructor
MyClass(){
//do things
}
};
int main(){
MyClass instance();
//now we override the function, something like:
instance.genericFunction(){
cout << "This new code exists only for this instance, and has been created outside the class!";
}
instance.genericFunction();
return 0;
}
So that's basically what I would like to do.
In the case that it is not possible, how can i make my class run a function that is going to be later defined in main()?
Thanks a lot!
EDIT: To answer your questions:
*I'm new to c++ and it's true that my background is from other languages
*The idea is the following: You are creating objects that have a position, and if the position is in a certain range, genericFunction() is executed. The thing is that for each instance the function that is executed may (or in fact should) be different. The idea is 'inspired' by android's clickListener, where each element has a different function to execute when clicked
Thanks again!
If you want to be able to set user defined functions for a class object then you can give it a member variable of type std::function. Using slightly different syntax from your example it could look like this:
class MyClass
{
public:
std::function<void()> genericFunction = []{};
};
int main()
{
MyClass instance;
instance.genericFunction(); // does nothing
// assign a lambda function to our
// function member
instance.genericFunction = []
{
std::cout
<< "This new code exists only for this instance, and has been created outside the class!";
};
instance.genericFunction(); // executes our lambda function
}
EDIT
If you want to be able to pass parameters or receive a return value, then change the template signature to std::function like this:
class MyClass
{
public:
// take a string parameter and return an integer
std::function<int(std::string const&)> genericFunction = [](std::string const&){ return 0; };
};
int main()
{
MyClass instance;
int return_value;
return_value = instance.genericFunction("This will do nothing and return 0"); // does nothing
std::cout << "The first function returned: " << return_value << '\n';
// assign a lambda function to our
// function member
instance.genericFunction = [](std::string const& msg)
{
std::cout << msg << '\n';
return 5;
};
return_value = instance.genericFunction("This will pint a message and return 5"); // executes our lambda function
std::cout << "The second function returned: " << return_value << '\n';
}
I am a learner of C++. I have compiled the below program. I am working on constructors and destructors concept. I have this code here below where I declare a private destructor and access the private members using member function of the class from main(). I know that a private constructor can be declared but is a public constructor also mandatory? here is my code below:
class Book
{
private:
int *pages;
int *price;
Book() //default constructor
{
pages = new int;
price = new int;
*pages = 300;
*price = 8;
}
public:
void pre_destructor()
{
std::cout << "The pages:" << *pages << "\n";
std::cout << "The price:" << *price << "\n";
}
~Book() //destructor
{
std::cout << "The pages:" << *pages << "\n";
std::cout << "The price:" << *price << "\n";
delete pages;
delete price;
}
};
int main()
{
using namespace std;
Book book1;
cout << "Before using destructors" << endl;
cout << "---------------------------------"<< endl;
book1.pre_destructor();
cout << "After using destructors" << endl;
cout << "---------------------------------";
return 1;
}
For the above program, two errors are shown. One is in the main function where an object is declared; Error: error within content. And the second one is in the line where the constructor is called; Error:Book::Book() is private.
The main is not directly accessing the constructor in the code. Then why does it shows the access error?
No, a public constructor is not mandatory. There are use cases for private constructors.
A class with only static methods might have private (or deleted) constructors to prevent instances being created.
A singleton class (where only one instance of the class exists) might enforce its singleton status by having a private constructor. That instance can be accessed through a static getter.
You might want to follow a builder or factory pattern, where you force your users to construct instances using a process beside calling the constructor. That builder or factory would be either a member of the class or a friend, so able to call a private constructor. This scheme is much more common in Java than C++, but C++ allows it as well.
That said, you're looking to simply construct an instance of a class:
Book book1;
This use definitely requires a public default constructor.
When you make a constructor private, you need to expose a method so that external classes/methods can create object of this class. You'd do so by creating a static method, which in turn creates the object.
following code demonstrates:
#include <iostream>
class Book
{
private:
int *pages;
int *price;
Book() //default constructor
{
pages = new int();
price = new int();
*pages = 300;
*price = 8;
}
public:
static Book* constructBook()
{
return new Book();
}
void pre_destructor()
{
std::cout << "The pages:" << *pages << "\n";
std::cout << "The price:" << *price << "\n";
}
~Book() //destructor
{
delete pages;
delete price;
}
};
int main()
{
Book* book1 = Book::constructBook();
std::cout << "Before using destructors" << endl;
std::cout << "---------------------------------"<< endl;
book1->pre_destructor();
cout << "After using destructors" << endl;
cout << "---------------------------------";
delete book1;
return 0;
}
Not at all ! You don't need a public constructor but you need a factory fuction to create an instance of that class & in that case you need to qualify that function with the keyword static. See below :-
#include <iostream>
using namespace std;
class X
{
int x;
X(int x)
{
cout<<"creation\n";
this->x = x;
}
public:
static X make_X (int x) // without static error message will be : error: cannot call member function 'X X::make_X(int)' without object
{
return X(x);
}
int& getx()
{
return x;
}
~X()
{
cout<<"destruction\n";
}
};
int main()
{
auto obj = X::make_X(5);
auto ano = X::make_X(7);
cout << obj.getx() << '\t' << ano.getx() << '\n';
return 0;
}
Output is :-
creation
creation
5 7
destruction
destruction
There is no need of a public contrcutor here. But you needed make_X to create an instance of the class.
You can also use friend instead of static. In that case the code will be :-
friend X make_X (int x); // declare a prototype in the class
Then define outside the class definition :-
X make_X (int x)
{
return X(x);
}
That's how it works ! Cheers!!
I am working on program in which I am require to use a priority queue. From my understanding the priority queue sorts the queue automatically from largest to smallest elements. I have create a simple priority queue of objects(nodes) that have a name and id number. I am trying to access the first object in the queue so I figured I could just use the "front" member function. This works when I use the standard queue but when I use a priority queue I get the error
error: 'class std::priority_queue' has no member named 'front'
I tried using "top" as well but then I get the error
error: passing 'const value_type (aka const node)' as 'this' argument
of 'void::display()' discards qualifiers [-fpermissive]
here is my code:
#include <iostream>
#include <queue>
using namespace std;
struct node
{
node(char n, int i) { name = n; id = i; }
void display() { cout << "name: " << name << " id : " << id << endl; }
friend bool operator < (node a, node b) { return a.id < b.id; }
private:
char name;
int id;
};
int main()
{
queue<node> myqueue; // Actually want a priority_queue<node>
myqueue.push(node('a',5));
myqueue.push(node('b',9));
myqueue.push(node('c',7));
myqueue.front().display(); // Error when using the type I want, even if I call top() instead
}
I will point out again that if I use queue instead of priority queue the code works. How do I access the front of a priority queue?
Your error is that .display() is not a constant member-function.
It should be:
void display() const { std::cout << "name: " << name << " id : " << id << '\n';}
As an aside, only use std::endl if explicitly flushing might be neccessary, as it flushes all hope of good performance down the drain.
Also read: Why is "using namespace std" considered bad practice?
Firstly, std::priority_queue::front does not exist. We just can't invoke something doesn't exist.
Secondly, be const-correct. Declare your member functions const.
void display() const
{...}
This is because the return type of std::priority_queue::top is a const reference. Via a const reference (and const value), only const member functions can be used. Inside a const member function, the object cannot be modified, which is the meaning of being const.
std::priority_queue::front does not exist.
Use
std::priority_queue::top
And yes, function display() should be const as mentioned by fellow member :)
void display() const { std::cout << "name: " << name << " id : " << id << '\n';}
I've messed up something.
Here is the code:
#include <iostream>
class connection_c {
private:
std::string data_;
void (*saveCallBack_)();
public:
connection_c(std::string &data) : data_(data) { std::cout << "ctor: " << __FUNCTION__ << ":" << data_ << std::endl;}
void registerCallBack(void(*cb)()) { saveCallBack_ = cb; }
};
class inst_c {
private:
static int id;
connection_c conn;
static void cb() { std::cout << __FUNCTION__ << " id = " << id << std::endl; }
public:
inst_c(connection_c &c, int a) : conn(c), id(a) {
std::cout << "ctor: " << __FUNCTION__ << " " << id << std::endl;
conn.registerCallBack(&cb);
}
};
class group_inst_c {
private:
connection_c conn;
inst_c i,j,k;
public:
group_inst_c(std::string data) : conn(data), i(conn,1), j(conn,2), k(conn,3) {}
};
int main() {
group_inst_c gi("asdf");
return 0;
}
What I want to achieve ;)
create a group of instances (group_inst_c)
it should initialize single connection for the group (connection_c)
each instance (inst_c) should use this connection (it will be serialized)
.. in addition each instance should register separate callback
For sure I've messed up with cloning, but I guess probably not only.
Can someone help me solve this puzzle? thx.
Your code creates a copy of your connection object for each instance. The original connection object is then only accessible by your group_inst_c. Is this what you want? If not, you need to change:
class inst_c {
private:
static int id;
connection_c& conn; // <-- Needs to be a reference.
in addition each instance should register separate callback
I'm not sure what you mean here. Are the callbacks supposed to be member functions? Then you need to use a "pointer to member function" (the ::*, .*, and ->* operators). If the callbacks are supposed to be regular functions, you should be okay with your current code. You'll just need to add this to class connection_c:
void doCallback(void) { (*saveCallBack_)(); }
If I understood that correctly (you want to call several callbacks from a single connection [object]), you need a list in connection_c to register the callbacks (just like delegates in C# if you know them).
If an event occurs to this connection, it has to know where to report. So you have to iterate through the callbacks somehow (call them one by one; you cannot call them all at once). The easiest, straightforward way is to use an STL list or maybe boost offers something appropriate.
Take a look at this: A C++ delegate class. In the main function, there's a vector defined that takes multiple callbacks. You could use this pattern in you connection_c class to add and not set a callback.
Try to keep it simple at first. There's always an opportunity to grow/improve the design later on. Below is some example code and here are a couple of things I was thinking about while building it:
1) As mentioned, keep it simple. For example, maybe the group concept can be a vector (i.e. inst_group_t) to start. You can always grow the design later as you learn more about it.
2) Try to reduce class dependencies. For example, maybe I do not need to have the connection as a member variable. I can pass it in when its needed (i.e. execute()). Maybe the callback doesn't need to be registered (i.e. execute()), since its 1 connection_c to many inst_c instances registering a callback for each inst_c would mean connection would have some container. Keep it simple :)
3) Try to use const and reference as much as possible (i.e. connection_c constructor). Less copy constructors/temp objects will be created.
#include <iostream>
class connection_c {
private:
std::string data_;
public:
connection_c(const std::string &data) : data_(data) {
std::cout << "ctor: " << __FUNCTION__ << ":" << data_ << std::endl;
}
};
class inst_c {
private:
int id;
public:
inst_c(int a) : id(a) {
std::cout << "ctor: " << __FUNCTION__ << " " << id << std::endl;
}
typedef void (*execute_callback_t)(int i);
void execute(connection_c& connection, execute_callback_t callback) {
callback(id);
}
};
void mycallback(int id) {
std::cout << "Instance number " << id << " executed" << std::endl;
}
int main() {
typedef std::vector<inst_c*> inst_group_t;
inst_group_t group;
std::string data;
connection_c connection(data);
for (int i = 0; i < 10; ++i)
group.push_back(new inst_c(i) );
for (int i = 0; i < 10; ++i)
group[i]->execute(connection, mycallback);
for (int i = 0; i < 10; ++i)
delete group[i];
return 0;
}