C++ classes and variables - c++

I'm relatively new to C++ programming. I'm studying how do classes work, and I have a problem with the following code:
#include <iostream>
using namespace std;
class time
{
public:
time();
void settime (int, int, int);
void printuniversal ();
void printstandard ();
private:
int hour;
int minute;
int second;
};
time::time()
{
hour = minute = second = 0;
}
void time::settime (int h, int m, int s)
{
hour = (h >= 0 && h < 24) ? h : 0;
minute = (m >= 0 && m < 60) ? m : 0;
second = (s >= 0 && s < 60) ? s : 0;
}
void time::printuniversal()
{
cout << hour << ":" << minute << ":" << second << ":" << endl;
}
void time::printstandard()
{
cout << ((hour == 0 || hour == 12) ? 12 : hour % 12) << ":" << minute << ":" << second << (hour < 12 ? "AM" : "PM") << endl;
}
int main ()
{
time t;
cout << "Initial universal time: " << t.printuniversal();
cout << "\nInitial standard time: " << t.printstandard();
t.settime(13,27,6);
cout << "\nNew universal time: " << t.printuniversal();
cout << "\nNew standard time: " << t.printstandard();
return 0;
}
The mistake I get is:
classi.cpp:42:6: error: expected ‘;’ before ‘t’
classi.cpp:43:39: error: ‘t’ was not declared in this scope
Is there something I didn't quite understand about classes? Why doesn't it recognize t a a "time" variable?

This should teach you not to have nasty using directives such as:
using namespace std;
And especially not at namespace scope (even worse if in header files). There is a function in the standard library called std::time(), whose name is clashing with the name of your type.
This ambiguity can be solved by using the class keyword in the declaration of t:
class time t;
However, a much better way would be to remove the using directive and qualify the names of entities from the standard namespace, thus writing (for instance):
std::cout << "Initial universal time: "
// ^^^^^
Notice, that this may not be enough, since library implementations are allowed to put entities from the C standard library in the global namespace. In this case, removing the nasty using directive would not help resolving the ambiguity.
Therefore, I would also suggest avoiding to give your own entities (types, functions, variables, ...) the same name as entities from the standard library, or to put them in your own namespace at least.
Moreover, expressions such as:
cout << "Initial universal time: " << t.printuniversal();
// ^^^^^^^^^^^^^^^^^^^^^
// printuniversal() returns void!
Are ill-formed, since printuniversal() returns void. You should just do:
cout << "Initial universal time: ";
t.printuniversal();
The same applies of course to all similar expressions

You shouldn't name your class time, or you should avoid using using namespace std. Instead, you can do statements like using std::cout, using std::endl, etc. I personally never use "using", always leave std::, it makes easier my searches in the source code.
Anyway, I checked here, removing using namespace std doesn't really help (see discussion above). Play safe and change name to the class. Anyway, the above suggestions stay.

An alternative to removing the "using namespace std" directive is to place your code in a namespace to avoid clashing names. This can be done as follows:
namespace time_utils
{
class time
{
public:
time();
void settime (int, int, int);
void printuniversal ();
void printstandard ();
private:
int hour;
int minute;
int second;
};
};
time_utils::time::time()
{
hour = minute = second = 0;
}
The purpose of namespaces is to avoid clashing names.
Later on there are compilation errors when calling functions in the cout stream, so you can split them up like so:
int main ()
{
my_code::time t;
cout << "Initial universal time: ";
t.printuniversal();
cout << "\nInitial standard time: ";
t.printstandard();
t.settime(13,27,6);
cout << "\nNew universal time: ";
t.printuniversal();
cout << "\nNew standard time: ";
t.printstandard();
return 0;
}
That's because those functions are returning void. The alternative there is to have those functions return std::string instead.
Hope this offers an alternative insight.
Cheers,
Simon.

Related

Call C++ recursive lambda in the same line where it is declared

This is mostly a one liner style type of question, I would normally write this code in multiple lines anyway for readability reasons.
So my question is can I call the recursive lambda in the same statement where it is defined?
So instead of this:
int n=3;
function<void(int)> f {[n,&f](int i){if (i>1) { cout << "func(a, "; f(i-1); cout << ")";} else cout << "a";}};
f(n);
call the function with n in the same line where f is defined.
In one statement which declares several variables ;-)
Mostly not what you want:
std::function<void(int)>
f {[&f](int i){
if (i>1) {
std::cout << "func(a, "; f(i-1); std::cout << ")";}
else
std::cout << "a";
}},
dummy((f(3), nullptr));
Demo
Let me offer a glimpse into the functional programming world, where people usually use combinators to deal with recursive lambdas. There was a proposal (P0200r0) last year to add a simple Y-combinator to the standard library.
Leaving aside the question whether it is a good idea to do this, this would allow you to write and invoke a recursive lambda like this:
y_combinator([](auto self, int i){
if (i>1) {
std::cout << "func(a, ";
self(i-1);
std::cout << ")";
} else {
std::cout << "a";
}
})(6);
The basic idea here is that the y-combinator is a higher order function that wraps a lambda which is passed 'itself' as a first argument. The combinator takes care of wrapping the self argument away for all invocations of the lambda.
You can try it in coliru.
As a matter of fact, you can. Here is a complete example which compiles and runs fine with g++ -std=c++11:
#include <iostream>
#include <functional>
int main() {
std::function<int(int)> f = ([&f](int i){ return i?f(i-1)*i:1; }), trash = (std::cout << f(3) << std::endl, f);
}
However, I don't think it's a good idea to actually use this: The construct , trash = (..., f) would be in order for code golf or obfuscated programming contests, but would not meet my standards for production code.
What you are essentially asking for is to create a temporary instance of std::function and then invoke operator() on that object in the same statement. Both of these fail to compile for me with the same error when I try that:
function<void(int)> f{[&f](int i){ if (i > 1) { cout << "func(a, "; f(i-1); cout << ")"; } else cout << "a"; }}(n);
function<void(int)> f([&f](int i){ if (i > 1) { cout << "func(a, "; f(i-1); cout << ")"; } else cout << "a"; })(n);
error: expected ‘,’ or ‘;’ before ‘(’ token
Pointing at the ( of (n).
See #Jarod42's answer for a viable workaround, if you don't mind the extra variable initialization.
Alternatively, this would work, though it does have to use separate variable declaration and assignment:
function<void(int)> f; f = [&f](int i){ if (i > 1) { cout << "func(a, "; f(i-1); cout << ")"; } else cout << "a"; }, f(n);
Demo
Not sure if you consider it valid since it doesn't use lambda functions, but it is still single line and leaves no temporal variables behind ;)
struct {
struct R {
R(int i) {
if (i>1) { cout << "func(a, "; R(i-1); cout << ")"; }
else cout << "a";
}
} r;
} f{n};

this code compiles but doesnt show output when it runs (c++) in visual studio 2015 community

#include <conio.h> // include conio.h file
#include <iostream.h> // or #include<iostream>
int main()
{
int cout = 5;
cout << cout;
return 0;
}
Why does this happen ??
The code compiles correctly but it does not give expected output when it runs
This does not give the output 5 and all other stuff
It also does not give a warning.
The following line declares an int that happens to be called cout (it is not the std::cout stream)
int cout = 5;
The << operator peforms a bit shift.
So
cout << cout;
is only performing a bit shift and not storing the result.
To clarify, have a look at the following program:
#include<iostream>
int main()
{
int cout = 5;
auto shiftedval = cout << cout;
std::cout << "cout's value is " << cout << ", and the result of the bit shift is " << shiftedval << '\n';
return 0;
}
It will output:
cout's value is 5, and the result of the bit shift is 160
What is happening behind the scenes is that operator<< has been overloaded to take an ostream on the left hand side.
By including iostream you get this function and the compiler will know what you mean if you have an ostream to the left of the << operator.
Without a library the << would just simply have been a bitwise shift operator.
Also note that if you had ill-advisedly included using namespace std; or using std::cout then cout would then mean ostream and << would trigger a call to the library operator<< function. If after adding the using declaration above you include another declaration of cout the newly declared name will hide the previous declaration and cout will now be considered an int again and we're back to the bit shift operator functionality being used.
Example:
#include<iostream>
using namespace std; // using std:: at global scope
int main()
{
int cout = 5;
auto shiftedval = cout << cout;
//the following will not compile, cout is an int:
cout << "cout's value is " << cout << ", and the result of the bit shift is " << shiftedval << '\n';
//but we can get the cout from the global scope and the following will compile
::cout << "cout's value is " << cout << ", and the result of the bit shift is " << shiftedval << '\n';
return 0;
}
You are naming your variable cout, which you are confusing with std::cout. Your example preforms a bit shift operation. Try this instead :
int main()
{
int cout = 5;
std::cout << cout;
return 0;
}
Better yet, name your variable anything else to avoid the confusion :
int main()
{
int foo = 5;
std::cout << foo;
return 0;
}
If you don't explicitly declare the std namespace, either by including using namespace std; in your code or calling std::cout then cout resolves to the local variable cout in your main() function.
Even if you do declare using namespace std; cout will still resolve to the local variable instead - this is one reason why a lot of people, books, and tutorials will recommend that you explicitly write std::whatever instead of using the namespace.

I am trying to use templates in c++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
#include <iostream>
using namespace std;
template <typename T>
void swap(T& i, T& j)
{
T temp = i;
i = j;
j = temp;
}
int main()
{
int m = 5, n = 10;
cout << "Inputs: " << m << "," << n << endl;
swap(m, n);
cout << "Outputs: " << m << "," << n << endl;
return 0;
}
However, I am getting compilation error. Can somebody help me to find the solution of this problem?
Your problem is using namespace std.
This is a perfect example of why "using namespace std;" screws you up when you least expect it with misleading and confusing error messages.
Remove "using namespace std" from your code, and always explicitly specify "std" when needed, i.e. std::cin, std::cout, etc....
You need to promise yourself that you will never write "using namespace std" ever again. Completely forget that this is a part of the C++ language.
The fixed version of your program, which compiles without any issues, is simply:
#include <iostream>
template <typename T>
void swap(T& i, T& j)
{
T temp = i;
i = j;
j = temp;
}
int main()
{
int m = 5, n = 10;
std::cout << "Inputs: " << m << "," << n << std::endl;
swap(m, n);
std::cout << "Outputs: " << m << "," << n << std::endl;
return 0;
}
swap() is already a defined function in the std namespace. Rename your method to something else.
using namespace std;
template <typename T>
void swaper(T& i, T& j)
{
T temp = i;
i = j;
j = temp;
}
int main()
{
int m = 5, n = 10;
cout << "Inputs: " << m << "," << n << endl;
swaper(m, n);
cout << "Outputs: " << m << "," << n << endl;
return 0;
}
The error message clearly says: error: call to 'swap' is ambiguous.
This is because swap is part of the namespace std.
And since you are using namespace std; - this is ambiguous!
You can solve this by either:
1.Remove the line using namespace std;
2.Rename the template function to something else
There is actually a number of problems in your code that cause the error message. And one contributor to the problem due to your implementation (i.e. the standard library you are using).
Firstly, you have defined a templated swap() with the same form (accepting two objects of the same type by reference) as an existing function named swap().
Second, the using namespace std tells the compiler that names in namespace std are candidates for matching names in your code. So, when the compiler sees your code swap(m,n) where m and n are int, it sees both your definition and the one in namespace std (i.e. std::swap() as viable candidates to match the name swap() in your code. Both candidates are able to accept two arguments of type (reference to) int, so the compiler has no reason to prefer one over the other. Hence it rejects your code with an error message about ambiguity.
The third problem is in your implementation (i.e. your compiler and its associated standard library) - <iostream> has apparently drawn in the definition of std::swap(). The problem is that <iostream> is neither required to do that (i.e. you cannot rely on it happening if you build your code with a different compiler) nor required not to (i.e. your code will compile alright with some compilers/libraries but not others).
In reality, std::swap() is required by the standard to be declared in <algorithm>, not in <iostream>.
Your options to get your code working with ALL compilers are therefore simple. A first option is to not define your own swap() at all, and rely on the standard library.
#include <iostream>
#include <algorithm> // Needed to guarantee visibility of std::swap()
using namespace std;
int main()
{
int m = 5, n = 10;
cout << "Inputs: " << m << "," << n << endl;
swap(m, n);
cout << "Outputs: " << m << "," << n << endl;
return 0;
}
A second option is to rename your function so it does not clash with std::swap().
#include <iostream>
using namespace std;
template <typename T>
void your_swap(T& i, T& j)
{
T temp = i;
i = j;
j = temp;
}
int main()
{
int m = 5, n = 10;
cout << "Inputs: " << m << "," << n << endl;
your_swap(m, n);
cout << "Outputs: " << m << "," << n << endl;
return 0;
}
A third option is to remove using namespace std from your code. This will allow you to safely declare your own swap(), without clashes with std::swap().
#include <iostream>
#include <algorithm>
template <typename T>
void swap(T& i, T& j)
{
T temp = i;
i = j;
j = temp;
}
int main()
{
int m = 5, n = 10;
std::cout << "Inputs: " << m << "," << n << std::endl;
swap(m, n);
std::cout << "Outputs: " << m << "," << n << std::endl;
return 0;
}
This last example will actually compile nicely - even with <algorithm> deliberately being used to draw in declarations of std::swap() - because the compiler has not been told to view names in std as candidates. It does require adding std:: prefixes to names in namespace std (std::cout, std::endl) that you intend to use. It will also compile nicely if swap(m,n) is replaced by std::swap(m,n).
A fourth option (which I normally would prefer in professional coding) is to rely on the standard library AND not employ using namespace std.
#include <iostream>
#include <algorithm> // Needed to guarantee visibility of std::swap()
int main()
{
int m = 5, n = 10;
std::cout << "Inputs: " << m << "," << n << std::endl;
std::swap(m, n);
std::cout << "Outputs: " << m << "," << n << std::endl;
return 0;
}
The short explanation of my preference for this option is that it avoids various other problems of ambiguity as well. The saved typing of not having to prefix std:: on names is not worth the trouble caused when other problems of ambiguity emerge.

Need help outputting things from different functions (C++)

I am fairly new to C++ and coding in general. I am trying to make just a basic little multiple choice type game for practice but I have run into a conundrum.
The program isn't outputting what I want it too. Here is the code:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
void sword(int damage);
void fists(int damage);
static int enemyHealth = 250;
int main() {
srand(time(0));
string SOF; //Abreveation for "Sword Or Fists"
cout << "You will be fighting a mean bad guy. Are you using a sword, or your fists?\n";
while (SOF != "sword" && SOF != "fists"){
cout << "Please enter your choice of either 'sword' or 'fists': ";
cin >> SOF;
}
cout << "Okay! Time to fight! \n";
if (SOF == "fists") {
void fists();
}
else if (SOF == "sword") {
void sword();
}
else{ (NULL); }
cout << "Congratulations! You have vanquished that foul beast!\n";
system("pause");
}
//This is for when the user chooses 'sword'
void sword(int damage = rand() % 100 + 50) {
while (enemyHealth > 0){
cout << "You deal " << damage << " damage with your sharp sword. \n";
enemyHealth -= damage;
}
}
//This is for when the user chooses 'fists'
void fists(int damage = rand() % 10 + 4) {
while (enemyHealth > 0){
cout << "You deal " << damage << " damage with your womanly fists. \n";
enemyHealth -= damage;
}
}
The first part works fine, but when I enter my choice of either "fists" or "sword" the output is:
Okay! Time to fight!
Congratulations! You have vanquished that foul beast!
But I want it to output the damage being done with either fists or sword.
If I could get some help with that, it would be amazing. Thanks!
void fists(); is a declaration, not a call, change to fists(); and sword();
Other things to look at:
Default parameters are declared in function declaration before main (or just move whole functions there)
Default parameters in c++ are evaluated once, so all 'hits' will be the same in your code
Local variable names are usually not named in uppercase, SOF looks loke it is a #defined constant or such.
To call the function, don't write void fists();, just
fists();
(What you have is a declaration, which has no useful effect here, rather than a call.)

<insert name of struct> was not declared in this scope

http://pastebin.com/4gvcQm7P
#include <iostream>
using namespace std;
int GenerateID()
{
static int nextID = 0;
return nextID++;
}
void PrintInformation(Employee EmployeeName)
{
cout << EmployeeName << "'s ID is: " << EmployeeName.ID << endl;
cout << EmployeeName << "'s age is: " << EmployeeName.age << endl;
cout << EmployeeName << "'s wage is: " << EmployeeName.wage << endl;
}
int main()
{
struct Employee
{
int ID;
int age;
float wage;
};
Employee Dominic;
Employee Jeffrey;
Dominic.ID = GenerateID();
Dominic.age = 22;
Dominic.wage = 7.10;
Jeffrey.ID = GenerateID();
Jeffrey.age = 28;
Dominic.wage = 7.10;
PrintInformation(Dominic);
PrintInformation(Jeffrey);
return 0;
}
/*
C:\CBProjects\Practise\main.cpp|11|error: variable or field 'PrintInformation' declared void|
C:\CBProjects\Practise\main.cpp|11|error: 'Employee' was not declared in this scope|
C:\CBProjects\Practise\main.cpp||In function 'int main()':|
C:\CBProjects\Practise\main.cpp|39|error: 'PrintInformation' was not declared in this scope|
||=== Build finished: 3 errors, 0 warnings (0 minutes, 0 seconds) ===|
*/
The above pastebin link shows the code I used and the build report. Following this report I attempted to forward declare the struct without including members and then there is an 'incomplete type' error.
What is the solution?
Edit: I'm using c++11
Edit 2: Here is what happens if I try to forward declare the struct, including the members:
http://pastebin.com/rrt4Yjes#
There are two solutions: Make Employee a non-local class/struct or make PrintInformation a template. For the first solution, just move Employee before PrintInformation. The second solution would be:
template< typename Employee >
void PrintInformation(const Employee& EmployeeName)
{
cout << " EmployeeName's ID is: " << EmployeeName.ID << endl;
cout << " EmployeeName's age is: " << EmployeeName.age << endl;
cout << " EmployeeName's wage is: " << EmployeeName.wage << endl;
}
Note that in any case you don't want a copy of Employee just to print some information, hence make the parameter of PrintInformation a constant reference as shown above.
First piece of information in the error is the line number.
C:\CBProjects\Practise\main.cpp|11|error: variable or field 'PrintInformation' declared void|
Line 11. Lets look at line 11.
void PrintInformation(Employee EmployeeName)
This all looks valid, but what's an Employee? We don't find that out until line 21. Your function, PrintInformation wants to make use of the internal plumbing of PrintInformation so the function actually needs to know the full definition of the struct/class.
In addition to all this, you have very explicitly made Employee a private type of main by defining it inside the function. What you are actually declaring is main::Employee.
A few solutions:
Declare "Employee" in the same scope as PrintInformation, i.e. at the global scope at the top of the file after the includes etc.
Or make "PrintInformation" a member function of Employee.
struct Employee
{
void PrintInformation()
{
std::cout << " Employee's ID is: " << ID << '\n';
std::cout << " Employee's age is: " << age << '\n';
std::cout << " Employee's wage is: " << wage << '\n';
}
...
};
...
Dominic.PrintInformation();
Or implement operator<< (probably advanced for where you are right now).
I'd also like to point out an aspect of style that is lining you up for some serious headaches down stream: You're using the same UpperCamelCase for variables and types, but being inconsistent with types. It's going to benefit you if you teach yourself to prefix member variables with something and maintain consistent case early on:
struct Employee // UpperCamel for types.
{
int m_id;
int m_age;
float m_wage;
};
It now becomes very easy to separate local variables and types and member variables. This is going to become especially useful as you start to learn about member functions.
struct Employee // UpperCamel for types.
{
int m_id;
std::string m_name;
int m_age;
float m_wage;
Employee(const std::string& name, int age, float wage)
: m_id(nextID++)
, m_name(name)
, m_age(age)
, m_wage(wage)
{}
...
};
You should declare struct Employee before using it in PrintInformation() or make PrintInformation a template (as #DanielFrey did).
Fix your PrintInformation() to following as you cannot directly print a struct data unless you overloading << for the struct (check out here on how to do this).
void PrintInformation(Employee EmployeeName)
{
cout << " EmployeeName's ID is: " << EmployeeName.ID << endl;
cout << " EmployeeName's age is: " << EmployeeName.age << endl;
cout << " EmployeeName's wage is: " << EmployeeName.wage << endl;
}