The task is to create class, which counts the objects of its type, in every moment. Here is my code. The errors are:
1. the object has type qualifiers that are not compatible with the member function "counter::print";
2. return value type does not match the function type; - this was obwious really!
I corrected the errors and it gives me new one that I can't fix;
1. 'void counter::print(void)': cannot convert 'this' pointer from 'const counter' to 'counter &'
class counter {
private:
static int count;
public:
counter();
counter(const counter &from);
void print() const;
~counter();
};
counter::counter() {
++count;
}
counter::counter(const counter &from) {
++count;
cout << "Copy constructor:\t";
from.print(); // here is the error
}
void counter::print() const{
cout << "\t Number of objects = " << count << endl;
}
counter::~counter() {
--count;
cout << "Destructor:\t\t";
print();
}
int counter::count = 0;
counter f(counter x);
void main() {
counter c;
cout << "After constructing of c:";
c.print();
cout << "Calling f()" << endl;
f(c);
cout << "After calling f():";
c.print();
}
counter f(counter x) {
cout << "Argument inside f():\t";
x.print();
return x;
}
Firstly, change:
void print();
to:
void print() const;
because (a) it's a const method anyway and (b) you're trying to call it in a const context within your constructor.
For the second error here:
void f(counter x) {
cout << "Argument inside f():\t";
x.print();
return x; // 2 - nd error
}
it should be fairly obvious that you can't return a value from a void function. Either change it to:
counter f(counter x) {
cout << "Argument inside f():\t";
x.print();
return x;
}
or simply don't return anything:
void f(counter x) {
cout << "Argument inside f():\t";
x.print();
}
void print();
You have declared a non-const member function, which means it cannot be called by const instances.
from.print(); // 1 - st error
Here the type of from is const counter& which means it cannot call the print function. Instead make your print function const.
void print() const;
void counter::print() const { ... }
return x; // 2 - nd error
Why are you returning anything from a function with a void return type?
Related
When we start learing about "Function Overloading" then we are given with the example of functions of same name but with either different number of parameters or different datatypes of parameters like:
void add(int a, int b) //function 1
{
cout << "sum = " << (a + b);
}
void add(double a, double b) //funciton 2
{
cout << endl << "sum = " << (a + b);
}
int main()
{
add(10, 2);
add(5.3, 6.2);
return 0;
}
In this both the overloaded add functions are delared globally and they have same scope(global) also.
Now, my question is that if I define two functions with same name inside different blocks(one as global and other one inside a class) then will it still be called as "Function Overloading"?
Like:
void display() //function 1
{
cout<<"global diaplay() function";
}
class example
{
public:
void display(char a) //funciton 2
{
cout<<"display() function inside a class called by passing argument:"<<a;
}
};
int main()
{
display();
example M;
M.display('o');
return 0;
}
Explaination with an example will be very helpful.
I have a templated class which wraps a std::vector called mObjects.
Class has an insert function which forwards parameters of the actually stored type in the MyArray instance (its called variadic template arguments I think). In this example, I store MyMesh type, but it can be any kind of type.
As you can see in the main() function, mObjects vector doesn't grow, its elements get overwritten over and over again.
Think about an object-pool kind of data structure.
Everything works as expected.
template <class T>
class MyArray
{
public:
MyArray(const int capacity) :
mObjects(capacity)
{
mNextIndex = 0;
}
template <typename... Args>
void insert(Args&&... args)
{
mObjects[mNextIndex] = T{ std::forward<Args>(args)... }; //PROBLEMATIC ASSIGNMENT
//... not relevant code
}
private:
int mNextIndex;
std::vector<T> mObjects;
};
int main()
{
MyArray<Mesh> sa(2);
sa.insert("foo",1111); //goes to mObjects[0]
sa.insert("bar",2222); //goes to mObjects[1], and tada, the vector is full
sa.remove(1111); //not implemented above, but not relevant. Remove func basically adjusts mNextIndex, so mObjects[0] will be overwritten upon next insert.
sa.insert("xxx",3333); //mObjects[0] gets overwritten from "foo" to "xxx" and 1111 to 3333
}
My problem is with one row above commented as //PROBLEMATIC ASSIGNMENT.
mObjects[mNextIndex] = T{ std::forward<Args>(args)... };
When that command executes 3 things happen:
MyMesh(const string s, int x) constructor is called, meaning an entire MyMesh gets allocated on stack here. Why? I just want to pass the forwarded arguments to an existing mObjects[mNextIndex] element.
operator=(MyMesh&& other) is called, and does assignment variable by variable between the temporary variable and mObjects[mNextIndex].
~cVMesh() is called meaning the temporary variable deallocates and dies.
I would like to get rid of #1 and #3. So don't want the "expensive" temporary object creation. I just wish to forward/assign the incoming MyMesh parameters to mObjects[mNextIndex]. Similarly like what std::vector.emplace_back() does, but to any location pointed by mNextIndex.
How can I forward only the parameters to an existing variable in C++, without instantiate temporary variables?
For completness, here is the MyMesh class which gets stored in the MyArray class. Nothing special just printing out some message, when constructor/destructor/assignement operator is called:
class Mesh
{
public:
Mesh()
{
cout << "Mesh()" << std::endl;
mStr = "";
mId = 99999999;
}
Mesh(const string s, int x)
{
cout << "Mesh(const string s, int x)" << std::endl;
mStr = s;
mId = x;
}
~Mesh()
{
cout << "~Mesh()" << std::endl;
}
Mesh& operator=(const Mesh& other)
{
cout << "operator=(const Mesh& other)" << std::endl;
cout << mStr << " becomes " << other.mStr << endl;
cout << mId << " becomes " << other.mId << endl;
mStr = other.mStr;
mId = other.mId;
return *this;
}
Mesh& operator=(Mesh&& other) noexcept
{
cout << "operator=(Mesh&& other)" << std::endl;
cout << mStr << " becomes " << other.mStr << endl;
cout << mId << " becomes " << other.mId << endl;
mStr = other.mStr;
mId = other.mId;
return *this;
}
Mesh(const Mesh& other)
{
cout << "Mesh(const Mesh& other)" << std::endl;
mStr = other.mStr;
mId= other.mId;
}
Mesh(Mesh&& other) noexcept
{
cout << "Mesh(Mesh&& other)" << std::endl;
mStr = other.mStr;
mId = other.mId;
other.mStr = "";
other.mId = 99999999;
}
string mStr;
int mId;
};
I think what you want is to reconstruct an arbitary element in the vector with new values
#include<vector>
template<class T, class... Args>
void create_at_nth_place(std::vector<T>& v, int n, Args&&...args){
auto& elem = v[n];
elem.~T();
new(&elem) T(std::forward<Args>(args)...);
}
struct S {
S();
S(int, bool);
template<class... Args>
S(Args&&...);
S(S&&) noexcept;
~S();
};
void f() {
std::vector<S> v(3);
create_at_nth_place(v, 2, 4323, false);
char a = 'a';
create_at_nth_place(v, 2, 'a', 123, 1232, 32.f, a);
}
Link: https://godbolt.org/g/3K9akZ
mObjects[mNextIndex] = T{ std::forward<Args>(args)... }; line creates a temporary object, performs a move(copy) assignment to object already stored in vector at specified position and finally destroys a temporary.
The whole MyArray class is rather useless since vector already has similar functionality.
vector<Mesh> sa;
sa.reserve(2);
sa.emplace_back("foo",1111); // Mesh constructor called once
sa.emplace_back("bar",2222); // Mesh constructor called once again
You might add:
void assign(const string& s, int x)
{
cout << "assign(const string s, int x)" << std::endl;
mStr = s;
mId = x;
}
And use it:
mObjects[mNextIndex].assign(std::forward<Args>(args)...);
If your mesh class is very heavy, you should consider having an array of pointers, this would eliminate spurious copies altogether. Wouldn't MyArray<std::shared_ptr<MyMesh>> work as is?
In the code below, why can I call printAlternativ but not print?
To my understanding, the object should be removed and neither should work.
using namespace std;
class MemTest
{
public:
MemTest(string);
~MemTest();
void print();
void printAlternative();
string name;
};
void MemTest::print() {
cout << "Print: " << name << "\n";
}
void MemTest::printAlternative() {
cout << "Print Alternative\n";
}
MemTest::MemTest(string n) {
cout << "Constructor\n";
name = n;
}
MemTest::~MemTest() {
cout << "Destructor\n";
}
void call(MemTest *b) {
MemTest a("TestName");
a.print();
b = &a;
}
int main()
{
MemTest *b = NULL;
call(b);
b->print(); // This crashes
// b->printAlternative(); This works
return 0;
}
After call() object get destructed, so now object b does not have any reference of any object and you are trying to access "name" data member of object because of that it get crashed.
You can verify it by adding a cout<<"Test line"; after call(b); line in main()
And why other one is working because member functions are associated with class and get assigned when first time we declare object and compiler only swipe data member in destructor()
#include <iostream>
using namespace std;
class Machine
{
class State *current;
public:
Machine();
void setCurrent(State *s)
{
current = s;
}
void on();
void off();
};
class State
{
public:
virtual void on(Machine *m)
{
cout << " already ON\n";
}
virtual void off(Machine *m)
{
cout << " already OFF\n";
}
};
void Machine::on()
{
current->on(this);
}
void Machine::off()
{
current->off(this);
}
class ON: public State
{
public:
ON()
{
cout << " ON-ctor ";
};
~ON()
{
cout << " dtor-ON\n";
};
void off(Machine *m);
};
class OFF: public State
{
public:
OFF()
{
cout << " OFF-ctor ";
};
~OFF()
{
cout << " dtor-OFF\n";
};
void on(Machine *m)
{
cout << " going from OFF to ON";
m->setCurrent(new ON());
delete this;
}
};
void ON::off(Machine *m)
{
cout << " going from ON to OFF";
m->setCurrent(new OFF());
delete this;
}
Machine::Machine()
{
current = new OFF();
cout << '\n';
}
int main()
{
void(Machine:: *ptrs[])() =
{
Machine::off, Machine::on
};
Machine fsm;
int num;
while (1)
{
cout << "Enter 0/1: ";
cin >> num;
(fsm. *ptrs[num])();
}
}
There are a few bits of code I don't completely understand.
First, what does this do exactly?
(fsm. *ptrs[num])();
It looks like it's calling a default constructor of state, but I am not totally sure. Also, I don't understand where the on and off method is called. I think the object machine is the calling object for the on and off method, but I am not even sure.
Lastly, why do we destroy this?
void on(Machine *m)
{
cout << " going from OFF to ON";
m->setCurrent(new ON());
delete this;
}
Is it only for memory management?
I have rewritten the code with two function pointers and some comments:
Instead of array of function pointers, I have used 2 diff pointers and I am using if else for making the decision for switching state.
Main:
int main()
{
void (Machine::*offptr)() = &Machine::off; //offptr is a member funct pointer that now points to Machine::off function
void (Machine::*onptr)() = &Machine::on; //onptr is a member funct pointer that now points to Machine::on function
Machine fsm;
int num;
while (1)
{
cout<<"Enter 0/1: ";
cin>>num;
if( num == 0 )
{
(fsm.*offptr)(); //Here your are calling the function pointed to by the offptr (i.e., Machine::off) using the pointer
}
else if( num == 1 )
{
(fsm.*onptr)(); //Here your are calling the function pointed to by the onptr (i.e., Machine::on) using the pointer
}
}
}
In your example, all the decision is taken with the help of pointer array indices it self. So if user presses 0 the function pointed by ptrs[0] will be called and for 1 the function pointed by ptr[1] will be called. But since there is no check to make sure the user entered 0/1, the program will crash if the user enters something other than 0 or 1.
void on(Machine *m)
{
cout << " going from OFF to ON";
m->setCurrent(new ON()); //Here you are changing the state of the machine from OFF to ON (Note: call comes to this function only if the previous state was OFF).
delete this; //The previous state instance (OFF state pointed by this pointer) of the machine is no more required. So you are deleting it.
}
I get three errors while i try to compile this program.
I am expecting the following output
OFF-ctor Enter 0/1: 0 already OFF Enter 0/1: 1
going from OFF to ON ON-ctor dtor-OFF Enter 0/1: 1
already ON Enter 0/1: 0 going from ON to OFF OFF-ctor
dtor-ON Enter 0/1: 1 going from OFF to ON ON-ctor
dtor-OFF Enter 0/1: 0 going from ON to OFF OFF-ctor
dtor-ON Enter 0/1: 0 already OFF Enter 0/1:
Following is the program
#include <iostream>
using namespace std;
class Machine
{
class State *current;
public:
Machine();
void setCurrent(State *s)
{
current = s;
}
void on();
void off();
};
class State
{
public:
virtual void on(Machine *m)
{
cout << " already ON\n";
}
virtual void off(Machine *m)
{
cout << " already OFF\n";
}
};
void Machine::on()
{
current->on(this);
}
void Machine::off()
{
current->off(this);
}
class ON: public State
{
public:
ON()
{
cout << " ON-ctor ";
};
~ON()
{
cout << " dtor-ON\n";
};
void off(Machine *m);
};
class OFF: public State
{
public:
OFF()
{
cout << " OFF-ctor ";
};
~OFF()
{
cout << " dtor-OFF\n";
};
void on(Machine *m)
{
cout << " going from OFF to ON";
m->setCurrent(new ON());
delete this;
}
};
void ON::off(Machine *m)
{
cout << " going from ON to OFF";
m->setCurrent(new OFF());
delete this;
}
Machine::Machine()
{
current = new OFF();
cout << '\n';
}
int main()
{
void(Machine:: *ptrs[])() =
{
Machine::off, Machine::on//Error2->invalid use of non-static member function 'void Machine::off()'
//Error3->invalid use of non-static member function 'void Machine::on()'
};
Machine fsm;
int num;
while (1)
{
cout << "Enter 0/1: ";
cin >> num;
(fsm. *ptrs[num])(); //Error1->expected unqualified-id before '*' token
}
}
The code was taken from sourcemaking.com under state design pattern.
I ran it in eclipse and linux g++.
Kindly help.
To get a pointer to a member function, you need to use an & (even though it's optional for getting a pointer to a non-member function): &Machine::off, &Machine::on
For the other, you need to realize that .* is a single token, so you need to remove the space between the two characters: (fsm.*ptrs[num])();
void (Machine::*ptrs[])() =
{
&Machine::off, // note: explicit &
&Machine::on
};
Machine fsm;
int num;
while (1)
{
cout << "Enter 0/1: ";
cin >> num;
(fsm.*ptrs[num])(); // note: no space between . and *
}
That still leaves the following warnings:
try.cc:19:22: warning: unused parameter 'm' [-Wunused-parameter]
try.cc:23:22: warning: unused parameter 'm' [-Wunused-parameter]
try.cc: In member function 'virtual void OFF::on(Machine*)':
try.cc:68:20: warning: deleting object of polymorphic class type 'OFF' which has non-virtual destructor might cause undefined behaviour [-Wdelete-non-virtual-dtor]
try.cc: In member function 'virtual void ON::off(Machine*)':
try.cc:76:14: warning: deleting object of polymorphic class type 'ON' which has non-virtual destructor might cause undefined behaviour [-Wdelete-non-virtual-dtor]