I am trying to learn C++ from the book Accelerated C++. At the end of Chapter 1 there is an exercise that tripped me. Essentially, I am wondering why the following code compiles and runs perfectly:
#include <iostream>
#include <string>
int main() {
{
const std::string s = "a string";
std::cout << s << std::endl;
{
std::cout << s << std::endl;
const std::string s = "another string";
std::cout << s << std::endl;
};
}
return 0;
}
It seems to me that I am doubly declaring the string s, and from my understanding this is illegal. Could you help me understand this better? Thanks. The output this produces is:
a string
a string
another string
In C++, you are allowed to redeclare a variable in a nested scope. Within that scope, the redeclared variable takes precedence.
See [basic.scope.hiding] for a standard reference:
A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived
class
These are two seperate variable because they are declared in a different scope. The scope of a variable is the 'area' of code in which it's visible.
The outer s is overwritten with s in inner body.
Related
In book "C++ Primer" fifth edition, there is a line "Entities with the same name defined in an outer scope are hidden" in the second page of Section 18.2.2. This sentence is underlined with red as follows:
I tried to repeat the claim in an experiment. The experimental code is as follows:
#include <cstdlib>
#include <iostream>
#include <cmath>
int abs(int n) {
std::cout << "here" << std::endl;
return 0;
}
void test() {
using std::abs;
std::cout << abs(7) << std::endl;
}
int main(int argc, char** argv) {
test();
return 0;
}
using std::abs is a using declaration, so, if the claim in "C++ Primer" is correct, the user-defined abs() function should be hidden by std::abs(). But the result is that it is the user-defined abs() function that is called. So, if the book is correct, there must be something wrong in my experiment. How do I write the experimental code to confirm the sentence in "C++ Primer"? If the book is incorrect, what should the correct exposition be that can replace the sentence? Thank you.
PS: I tried in both Windows10+VS2015 and Ubuntu 18.04+g++7.4. Both called user-defined abs() and printed out "here".
The book could do a better job of explaining it, but it isn't wrong. It's just that the lookup rules for overloads are somewhat more nuanced, because overloads of the same name may coexist in the same scope normally, so a using declaration mingles well with that.
If you were to indeed define a new entity that is not an overload, for instance
void test() {
int abs = 0;
std::cout << abs(7) << std::endl;
}
Then that call expression would be ill-formed, because the outer callable entities are hidden by the inner int variable. The way to work around it would be with a using declaration
void test() {
int abs = 0;
{
using std::abs; // Let the name refer to the functions again
using ::abs; // the variable abs is hidden
std::cout << abs(7) << std::endl;
}
}
This experiment should illustrate what the book meant.
I'm beginner in C++. I learned from the book "accelerated c++" about a const variable inside a block scope. It means that the "const variable will be destroyed when the scope ends at }.
But in the test: the const string variable s is defined inside the first block. In the second block, the s is also defined. When the second s is printed out the first block's s hasn't been destroyed.
I think the program is invalid, but the result is totally true when I compile the program. I don't known why it is. please help me to understand the code.
#include <iostream>
#include <string>
int main()
{
const std::string s = "a string";
std::cout << s << std::endl;
{
const std::string s = "another string";
std::cout << s << std::endl;
}
return 0;
}
the result is
a string
another string
Enlarge your program the following way
#include<iostream>
#include<string>
const std::string s = "a first string";
int main()
{
std::cout << s << std::endl;
const std::string s = "a string";
std::cout << s << std::endl;
{
const std::string s = "another string";
std::cout << s << std::endl;
}
std::cout << s << std::endl;
std::cout << ::s << std::endl;
return 0;
}
The program output is
a first string
a string
another string
a string
a first string
Each declaration in an internal scope hides a declaration in the outer scope with the same name (except function names that can be overloaded). But the variable declared in the outer scope is still alive. If a variable is declared within a namespace as the first variable s that is declared before main and belongs to the global namespace then you can use its qualified name to access the variable.
When an unqualified name is used then the compiler searches its declaration starting with the nearest scope.
This is solely for example I happen to notice with!
I'm using cout with operator<< and why won't this program compile?
Why aren't they being considered the way function overloadings are?
#include <iostream> // imports the declaration of std::cout
using namespace std; // makes std::cout accessible as "cout"
int cout() // declares our own "cout" function
{
return 5;
}
int main()
{
cout << "Hello, world!"; // Compile error!
return 0;
}
At the point of the attempted stream insertion, there are two names cout in global scope: one from the standard library, std::cout, pulled into global scope by that infernal using declaration, and one defined as a function int cout(). In the expression
cout << "Hello, world!\n";
the use of cout is ambiguous. There is no function overloading for two reasons: first, std::cout is not a function, so would not take part in overloading. But more fundamentally, the use of cout in that expression is not a function call, so, again, there is no overloading. The name cout from the function definition is treated as a pointer to function, and the name cout from namespace std is the name of an object. There are two possible interpretations of that name, so its use in that << expression is ambiguous.
I can't figure out why I get this error: "the function was not declared". I am still a newbie at programming, but I am trying my best to learn it!
so here is my code, I would be realy greatful if you could help me:
main:
#include <iostream>
#include <vector>
#include "szovegkezelo.h"
using namespace std;
int main()
{
string sz;
beolvas(sz);
kiir(sz);
return 0;
}
header:
#ifndef SZOVEGKEZELO_H_INCLUDED
#define SZOVEGKEZELO_H_INCLUDED
#include <iostream>
using namespace std;
class szovegkezelo {
protected:
string sz;
public:szovegkezelo
void beolvas(string &sz);
void kiir(string t);
};
#endif // SZOVEGKEZELO_H_INCLUDED
cpp:
#include "szovegkezelo.h"
#include <iostream>
void szovegkezelo::beolvas(string &sz)
{
getline(cin, sz);
}
void szovegkezelo::kiir(string t)
{
cout << "a beadott szoveg: " << t << endl;
cout << "a string hossza: " << t.size() << endl;
}
From what it looks like, you are trying to call a classes function (method) called 'beolvas' from 'main' but because it belongs to a class, you can't call it like that, you need to create an instance of that class and call the method on that instance, or make the function static and call it from the class.
Your first option is to create an instance of the class and then call the methods on the class like so:
int main()
{
string sz;
szovegkezelo szov;
szov.beolvas(sz);
svoz.kiir(sz);
return 0;
}
Your second option is to make the functions in your class static, this way they will not need an instance of the class to be called:
int main()
{
string sz;
szov::beolvas(sz);
svoz::kiir(sz);
return 0;
}
static void szovegkezelo::beolvas(string &sz)
{
getline(cin, sz);
}
static void szovegkezelo::kiir(string t)
{
cout << "a beadott szoveg: " << t << endl;
cout << "a string hossza: " << t.size() << endl;
}
Been a while since I've done anything static in c++ so please correct me if I've done something wrong in the second option.
Your two or more data types... error comes from a misuse of...something...after that public access specifier.
Change this:
public:szovegkezelo
to this:
public:
If you're trying to make a constructor, it needs to be declared like any other function, minus the return type.
Your other error occurs because this function was declared improperly.
Other than that, you need to create an object before you can call the class's functions. Each object has it's own set of variables that the functions work on. I would seriously recommend reading a good beginner C++ OOP book.
Somewhere in main, you need to create an object:
szovegkezelo myObject;
Then, use it to call functions:
myObject.kiir (sz);
Finally, note that your data members should typically be declared with the private access specifier. protected has nothing to do with normal classes that are not inherited from.
couple of things :
1) In main you have not instantiated an object of szovegkezelo and you are trying to call beolvas . Compiler is looking for a free function beolvas whereas you have declared beolvas as member function
2) public:szovegkezelo is not right if you are looking for a default constrcutor that does nothing don't have that line else if you need to do something specific with default construct declare it as szovegkezelo() in header.
3) as mentioned in comments it is not a good practice to put
using namespace std in header files or any using namespace
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What is the meaning of prepended double colon “::” to class name?
I have been looking at a legacy C++ code and it had something like this:
::putenv(local_tz_char);
::tzset();
What does this syntax of prepending "::" to the function calls mean? Google-fu is failing me.
It means that the functions putenv() and tzset() will be looked up by the compiler in the global namespace.
Example
#include <iostream>
using namespace std;
//global function
void foo()
{
cout << "This function will be called by bar()";
}
namespace lorem
{
void foo()
{
cout << "This function will not be called by bar()";
}
void bar()
{
::foo();
}
}
int main()
{
lorem::bar(); //will print "This function will be called by bar()"
return 0;
}
Also known as Scope resolution operator
In C++ is used to define the already declared member functions (in the
header file with the .hpp or the .h extension) of a particular class.
In the .cpp file one can define the usual global functions or the
member functions of the class. To differentiate between the normal
functions and the member functions of the class, one needs to use the
scope resolution operator (::) in between the class name and the
member function name i.e. ship::foo() where ship is a class and foo()
is a member function of the class ship.
Example from Wikipedia:
#include <iostream>
// Without this using statement cout below would need to be std::cout
using namespace std;
int n = 12; // A global variable
int main() {
int n = 13; // A local variable
cout << ::n << endl; // Print the global variable: 12
cout << n << endl; // Print the local variable: 13
}
There was a discussion yesterday (+ a year) on a similar question. Perhaps you can find a more indepth answer here.
What is the meaning of prepended double colon "::"?
It means: look up the function in the global namespace.
It will use the specifically unqualified name (as opposed to anything imported with the using keyword).
the :: is the scope resolution operator, it tells the compiler in what scope to find the function.
For instance if you have a function with a local variable var and you have a global variable of the same name, you can choose to access the global one by prepending the scope resolution operator:
int var = 0;
void test() {
int var = 5;
cout << "Local: " << var << endl;
cout << "Global: " << ::var << endl;
}
The IBM C++ compiler documentation puts it like this (source):
The :: (scope resolution) operator is used to qualify hidden names so
that you can still use them. You can use the unary scope operator if a
namespace scope or global scope name is hidden by an explicit
declaration of the same name in a block or class.
The same can be done for methods inside a class and versions of the same name outside. If you wanted to access a variable, function or class in a specific namespace you could access it like this: <namespace>::<variable|function|class>
One thing to note though, even though it is an operator it is not one of the operators that can be overloaded.