namespace and private static class members - c++

Why does this work:
#include "iostream"
class Something {
private:
static int s_nIDGenerator;
int m_nID;
friend int main();
public:
Something() { m_nID = s_nIDGenerator++; }
int GetID() const { return m_nID; }
};
int Something::s_nIDGenerator;
int main() {
Something::s_nIDGenerator = 1;
Something cFirst;
Something cSecond;
Something cThird;
using namespace std;
cout << cFirst.GetID() << endl;
cout << cSecond.GetID() << endl;
cout << cThird.GetID() << endl;
return 0;
}
it prints:
1
2
3
And this fail:
#include "iostream"
namespace test {
class Something {
private:
static int s_nIDGenerator;
int m_nID;
friend int main();
public:
Something() { m_nID = s_nIDGenerator++; }
int GetID() const { return m_nID; }
};
};
int test::Something::s_nIDGenerator;
int main() {
using namespace test;
Something::s_nIDGenerator = 1;
// or test::Something::s_nIDGenerator = 1; same effect if not using using.
Something cFirst;
Something cSecond;
Something cThird;
using namespace std;
cout << cFirst.GetID() << endl;
cout << cSecond.GetID() << endl;
cout << cThird.GetID() << endl;
return 0;
}
With the compiler error message of:
**** Internal Builder is used for build ****
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o src\tuttest1.o ..\src\tuttest1.cpp
..\src\tuttest1.cpp: In function 'int main()':
..\src\tuttest1.cpp:23:5: error: 'int test::Something::s_nIDGenerator' is private
..\src\tuttest1.cpp:27:13: error: within this context
Build error occurred, build is stopped
Time consumed: 161 ms.
How do I get the 2nd example to work using the namespace test?
How/Why is the namespace declaration around the object preventing the static member form being accessible?
Per my comment to #zmo, here is what I got to work based on his clue:
(comment doesn't have the space or formatting for this, and I had to edit because I couldn't set this an answer.... (what ever it takes.)
#include "iostream"
namespace test {
class Something {
private:
static int s_nIDGenerator;
int m_nID;
friend void load(int);
public:
Something() { m_nID = s_nIDGenerator++; }
int GetID() const { return m_nID; }
};
int Something::s_nIDGenerator;
void load (int value) {
Something::s_nIDGenerator = value;
}
};
int main() {
using namespace test;
load (1);
Something cFirst;
Something cSecond;
Something cThird;
using namespace std;
cout << cFirst.GetID() << endl;
cout << cSecond.GetID() << endl;
cout << cThird.GetID() << endl;
return 0;
}
I am still a little loose as to the "what's up with static members being in a class and a namespace not working?" What's up with this? Why didn't test::Something::s_nIDGenerator work? (still a part of my original question.) So, we are half-answered, so far.
I want to know why this didn't work so I don't walk into this rake again.

Probably because your friend int main() declaration is declaring that the namespace also has a free main() function, while the real main() function is not in the namespace.
To fix it? First declare int main(); before (and outside) namespace test, then friend int ::main() to indicate it's in the global namespace.
For more details, see this question.

well, though I will never recommand you to do like you did in your question, here is how to make your code work "as is" :
#include <iostream>
int main(); // declare main beforehands so it can be seen by Something
namespace test {
class Something {
private:
static int s_nIDGenerator;
int m_nID;
friend int ::main(); // take the main from global namespace
public:
Something() { m_nID = s_nIDGenerator++; }
int GetID() const { return m_nID; }
};
};
int test::Something::s_nIDGenerator;
int main() {
using namespace test;
Something::s_nIDGenerator = 1; // tada that works
Something cFirst;
Something cSecond;
Something cThird;
using namespace std;
cout << cFirst.GetID() << endl;
cout << cSecond.GetID() << endl;
cout << cThird.GetID() << endl;
return 0;
}
but here is a wrong use case of a friend function. The solution that seemed to work for you that I suggested (use a function inside your class Something) is far better for readability and understandability.

Related

Why the garbage values is coming after account balance

When I am executing this, a garbage value is coming with account balance info. Can anyone help me why?
#include<bits/stdc++.h>
using namespace std;
class Bankaccount
{
public:
int accnumber,accbalance;
int display()
{
cout<<"Account number is: "<<accnumber;
cout<<"\nAccount balance is: "<<accbalance;
}
};
int main() {
Bankaccount a;
Bankaccount b;
a.accnumber = 123456;
a.accbalance =50;
b.accnumber = 67890;
b.accbalance = 2000;
cout<<"Account details of A\n\n"<<a.display()<<endl;
cout<<"\nAccount details of B\n\n"<<b.display();
return 0;
}
The function display() should return void in this case. Your version has in its signature that it returns int, but then you don't return anything. This leads to undefined behavior.
Also it is bad practice to use using namespace std and #include<bits/stdc++.h>.
Read up here Why is "using namespace std;" considered bad practice?
And here How does #include <bits/stdc++.h> work in C++?
#include <iostream>
class Bankaccount
{
public:
int accnumber, accbalance;
void display()
{
std::cout << "Account number is: " << accnumber << "\n";
std::cout << "Account balance is: " << accbalance << "\n";
}
};
int main()
{
Bankaccount a;
Bankaccount b;
a.accnumber = 123456;
a.accbalance =50;
b.accnumber = 67890;
b.accbalance = 2000;
std::cout<<"Account details of A\n\n";
a.display(); // this is how to use display
std::cout<<"\nAccount details of B\n\n";
b.display();
return 0;
}
You are inserting to std::cout, among others, result returned from function display
which should be int, but, considering that your function has no return statement everything is possible, basically you are sending undefined value to ostream cout, and that is what garbage is by definition.
Most probably this is what you wanted to achieve:
https://wandbox.org/permlink/bpPth9WutHaiU5jQ
#include <bits/stdc++.h>
using namespace std;
class Bankaccount {
public:
int accnumber, accbalance;
std::ostream& display(std::ostream& out) const
{
out << "Account number is: " << accnumber;
return out << "\nAccount balance is: " << accbalance;
}
};
std::ostream& operator<<(std::ostream& out, const Bankaccount& acc)
{
return acc.display(out);
}
int main()
{
Bankaccount a;
Bankaccount b;
a.accnumber = 123456;
a.accbalance = 50;
b.accnumber = 67890;
b.accbalance = 2000;
cout << "Account details of A\n" << a << endl;
cout << "\nAccount details of B\n" << b << endl;
return 0;
}
Your int display() function doesn't return an int so you'll have undefined behaviour after that function has been called. If it had returned an int, that number had been printed, but I suspect that's not what you wanted.
The garbage you see is an int picked from the stack (because display() was supposed to put an int there). It was put the for a reason by some other function, but now it's gone, so anything can happen. To avoid this, you could declare your function void display() - but then you wouldn't be able to stream it, which is what it looks like you want to do.
If you want to be able to stream your objects, you need to define streaming operators to do the job. I've replaced your display() function with an out stream operator (operator<<) here:
#include <iostream>
//#include<bits/stdc++.h> // non-portable, don't use it
// using namespace std; // brings in too much in the namespace
using std::cout; // prefer this or just write std::cout everywhere
class Bankaccount {
public:
int accnumber, accbalance;
friend std::ostream& operator<<(std::ostream& os, const Bankaccount& ba) {
return os << "Account number is : " << ba.accnumber
<< "\nAccount balance is: " << ba.accbalance << "\n";
}
};
int main() {
Bankaccount a;
Bankaccount b;
a.accnumber = 123456;
a.accbalance = 50;
b.accnumber = 67890;
b.accbalance = 2000;
// std::endl is approx. the same as "\n" + std::flush. You don't need flushing.
cout << "Account details of A\n\n" << a << "\n";
cout << "\nAccount details of B\n\n" << b << "\n";
}

"undefined identifier" despite defining it in the class.

im a beginner in c++ and i am so confused why i am getting an error in my code, could you guys please tell me whats going wrong? im using visual studios 2017.
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class Cat {
private:
bool happy;
public:
void speak() {
cout << "meow" << endl;
}
Cat() {
bool newHappy = happy;
happy = true;
}
};
int main()
{
cout << "Starting program..." << endl;
Cat bob;
bob.speak();
if (happy) {
cout << "cat is happy" << endl;
}
else {
cout << "unhappy cat" << endl;
}
cout << "Ending program..." << endl;
return 0;
}
You're trying to reference a variable called happy inside your main function, which doesn't exist in that scope. If you want to see if bob is happy, you could simply write if (bob.happy){ ... and change Cat::happy from private to public, or you could create a getter function like:
class Cat {
private:
bool happy;
public:
bool isHappy() const {
return happy;
}
...
};
and call the function as follows: if (bob.isHappy()){ ...

Cleanup at unexpected function end, std equivalent

I have some function where I need to use a member variable(a vector of custom classes).
At the end of this function this member needs to be cleared but it needs to stay as a member for the duration of this function.
Another problem is that the function can end prematurely due to custom error handling of the program. Yet the member still needs to be cleared.
I first moved this member at the beginning in a local variable using std::move.
This worked pretty well but it now turns out I need the variable to stay as a member variable till the end of that function.
I came up with the following solution using a unique_ptr with a reference that will do the move upon destruction.
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
template <class T>
class Clean
{
public:
Clean(T& clean)
: m_clean(clean) {}
~Clean()
{
T destroy = move(m_clean);
}
private:
T& m_clean;
};
class A
{
public:
A()
{
m_numbers = { { 3, 1 ,4, 1, 5} };
}
void display()
{
auto cleanNumbers = make_unique<Clean<vector<int> > >(m_numbers);
for(int number: m_numbers)
cout << number << endl;
}
private:
vector<int> m_numbers;
};
int main()
{
A a;
a.display();
cout << "should be empty now" << endl;
a.display();
return 0;
}
Any cleaner solutions are also welcome but my actual question is the following.
Is there any std equivalent of the Clean class I used?
Ps: code fragment compiles for me using g++ 5.3.0
g++ -std=c++14 -o main main.cpp
This is the result I came to thanks to comments and other questions:
void display()
{
auto cleanNumber = [](decltype(m_numbers)* numbers){
if(numbers)
numbers->clear();
};
auto pClean = std::unique_ptr<decltype(m_numbers), decltype(cleanNumber)>(&m_numbers, cleanNumber);
for(int number: m_numbers)
cout << number << endl;
}
You could use a shared_ptr's custom deleter to obtain the same result.
void A::display()
{
std::shared_ptr<int> dummy (
(int*)alloca(sizeof(int)), // very fast allocate on stack
[&](int*) { this->m_numbers.clear(); }
);
for(int number: m_numbers)
cout << number << endl;
}
Here is the entire code, compiles fine, gcc 5.3 -Wall -Wpedantic -march=native -std=c++14
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
class A
{
public:
A()
{
m_numbers = { { 3, 1 ,4, 1, 5} };
}
void display()
{
std::shared_ptr<int> dummy (
(int*)alloca(sizeof(int)),
[&](int*) { this->m_numbers.clear(); }
);
for(int number: m_numbers)
cout << number << endl;
}
private:
vector<int> m_numbers;
};
int main()
{
A a;
a.display();
cout << "should be empty now" << endl;
a.display();
return 0;
}

how to use struct in a class

lifeform.h
class lifeform
{
public:
struct item;
void buyItem(item &a);
//code..
};
lifeform.cpp
struct lifeform::item
{
std::string type,name;
bool own;
int value,feature;
item(std::string _type,std::string _name,int _value,int _feature):type(_type), name(_name),value(_value),feature(_feature)
{
own=false;
}
};
lifeform::item lBoots("boots","Leather Boots",70,20);
void lifeform::buyItem(item &a)
{
if(a.own==0)
{
inventory.push_back(a);
a.own=1;
addGold(-a.value);
std::cout << "Added " << a.name << " to the inventory.";
if(a.type=="boots")
{
hp-=inventory[1].feature;
inventory[1]=a;
std::cout << " ( HP + " << a.feature << " )\n";
maxHp+=a.feature;
hp+=a.feature;
}
}
there is no error so far but when i wanna use them in main.cpp like this
#include "lifeform.h"
int main()
{
lifeform p;
p.buyItem(lBoots);
}
compiler says me [Error] 'lBoots' was not declared in this scope but i declared it class am i missing something?
To use your lifeform::item lBoots you need to declare it in main:
#include "lifeform.h"
extern lifeform::item lBoots; // <-- you need this.
int main()
{
lifeform p;
p.buyItem(lBoots);
}
Or alternatively you should place extern lifeform::item lBoots; in your lifeform.h.

C++ Inheritance problem

I hope I got the relevant code in here. I have some problem when I want to fetch the menu option that I've added into to menu_1. I have this function on_select(int) that I use to fetch one sub-menu's options, which I do by using the display() function. But when I compile it will say that there are no function named display() in menu_option() class, which is the Base class, but what I want to is to access the display() function which is located in the sub_menu() class.
I have tried multiple thing to get the relevant object from the array without any success, so I'm here now asking for help with this one.
I have this following main()
#include <iostream>
using namespace std;
#include "menu.h"
int main()
{
sub_menu* main_menu = new sub_menu("Warehouse Store Menu");
sub_menu* menu_1 = new sub_menu("Menu1");
main_menu->add_option(new sub_menu("Menu2"));
main_menu->add_option(menu_1);
product_menu->add_option(new add_item("sub_item1"));
product_menu->add_option(new add_item("sub_item2"));
product_menu->add_option(new add_item("sub_item3"));
main_menu->display();
main_menu->on_select(1);
delete main_menu;
return 0;
}
header file
#include <iomanip>
#include <iostream>
#include <string>
using namespace std;
const int MAX_SIZE = 9;
class menu_option
{
public:
menu_option(string const& n) : title(n) {};
virtual ~menu_option();
virtual void on_select(int) = 0;
string get_title() { return title; }
protected:
string title;
};
/* ------------------------------------- */
class sub_menu : public menu_option
{
public:
sub_menu(string const& n)
: menu_option(n) { no_item = 0; }
~sub_menu() { delete[] list; };
void on_select(int);
void add_option(menu_option*);
void display();
private:
menu_option* list[MAX_SIZE]; //container for options in the sub_menu
int no_item;
};
implement file
void sub_menu::on_select(int i)
{
cout << (list[i])->get_title() << endl;
cout << (list[i])->display() << endl; //<------ Doesn't work
}
void sub_menu::add_option(menu_option* item)
{
list[no_item] = item;
no_item++;
}
void sub_menu::display()
{
cout << ">> " << get_title() << " <<"<< endl;
for( int i = 0; i < no_item; i++ )
{
cout << setw(2) << i << ": " << (list[i])->get_title() << endl;
}
}
You can do what you want to do, but it's bad. You have to cast down to sub_menu when you call display() in on_select(). Of course it's not going to work the way you have it, and the compiler is telling you exactly why.
The other option, which is probably better (though without a clear understanding of the problem space may not be the best) would be to add display() as a virtual function to the menu_option class.
To solve your immediate problem you'll want to use dynamic_cast to turn a menu_option* into a sub_menu*, like so:
sub_menu* submenu(dynamic_cast<sub_menu*>(list[i]));
Note that if the cast fails (i.e., the menu_option pointed to by list[i] is not a sub_menu after all) the value of the submenu pointer will be NULL, so make sure you check that it is a valid pointer before using it in subsequent code.