Sorry for this question but I am stuck.
I have folowing syntax:
class xx
{
..some simple fields like: int t; // )))
public: class anotherClass;
xx();
MyObj* obj();
string* name(); //error C2143: syntax error : missing ';' before '*'
}
i have write # include <string>
What does compiler wants from me?!
It wants you to tell him which string. You want the standard one:
class xx
{
public:
std::string* name();
};
Now, I'm not sure why you would be returning a pointer to a string. That's a segmentation fault waiting to happen, if you ask me. Two more viable options that seem reasonable to me:
class xx
{
std::string _name;
public:
const std::string& name() const
{
return _name; // WARNING: only valid as long as
// this instance of xx is valid
}
};
or
class xx
{
public:
std::string name() const { return "hello world"; }
};
You need to either fully qualify string or bring it into the current namespace:
std::string* name();
or
using std::string;
In a header, it's generally considered bad practice to pollute the global namespace, so the first is preferred.
The compiler does not know what string is because string is residing in the namespace std, not in the global namespace. You need to change string to std::string.
In your cpp file you can use "using namespace std;" or "using std::string;" and then just write "string". But you should never use using-namespace-declarations in header files.
BTW, as the others say returning a string* is unusal, normally you would return a string.
Related
Why am I am getting an "expected identifier" error before .token?
Please provide a solution to understand friend function properly.
At first, I am getting a forward declaration error, but I resolved that one by myself.
#include<iostream>
using namespace std;
class a;
class b
{
public:
void search(a and);
};
class a
{
string name;
friend void b::search(a and);
public:
};
void b::search(a and)
{
cout << and.name;
}
int main()
{
}
For compatibility with old keyboards and encoding schemes where some symbols weren't available, certain keywords can be used in place of symbols. Among them, and is a valid replacement for &&. So your and.name is actually getting parsed as &&.name, which is a syntax error.
The (unfortunate) solution to your problem is: Don't name variables and or any of the other words on that list.
This is a follow-up question from: constructing string from NULL?
The following:
void test(const std::string& s);
int main(){
test(NULL);
}
Fails when run, but is legal c++.
In order to try to catch some of those cases, as an alternative ive considering if std::string can be replaced in the following way:
#include <string>
namespace {
namespace std {
struct string : public ::std::string { //so far everything is good
};
}
}
int main ()
{
std::string hello;//failure: ambiguous symbol
return 0;
}
Gives the following error:
<source>(17): error C2872: 'std': ambiguous symbol
C:/data/msvc/14.22.27905/include\string(19): note: could be 'std'
<source>(7): note: or '`anonymous-namespace'::std'
<source>(17): error C2872: 'std': ambiguous symbol
C:/data/msvc/14.22.27905/include\string(19): note: could be 'std'
<source>(7): note: or '`anonymous-namespace'::std'
Compiler returned: 2
I guess it is not possible to make it resolve without writing a more (fully) qualified name ? but is it possible to write std::string in the global namespace and have it resolve to something else while ::std::string is a valid type.
Background: after some failed attempts with cppcheck and cpp core check im trying to find all cases of std::string str = 0 or NULL or nullptr - since those will fail at runtime. And I thought this might be a way forward.
I ended up modifying the basic_string template ala. basic_string(int) = delete;
basic_string(::std::nullptr_t) = delete; - this won't catch all cases but does indeed seem to catch the direct cases at least
Resolve std::string to something else than ::std::string - is it possible?
[...]
...as an alternative ive considering if std::string can be replaced in the following way...
As far as I know, it is not possible outside of your anonymous namespace scope because you have no way to resolve the ambiguity (not to my knowledge).
As you can see below, since you are inside the scope of the anonymous namespace, it will be fine:
#include <string>
namespace
{
namespace std
{
struct string : public ::std::string
{
};
}
std::string hello; // Fine
}
int main()
{
std::string hello2; // Cannot be something else that ambiguous
return 0;
}
But even worse, the problem is not about std::string itself but about the std namespace.
Indeed, outside of the scope of your anonymous namespace, every call of std becomes ambiguous too.This is the error pointed by the compiler. There are two std namespaces accessible as is from the global scope.
So the following example becomes broken:
#include <string>
#include <vector>
namespace
{
namespace std
{
struct string : public ::std::string
{
};
}
std::string hello; // Fine
}
int main()
{
std::vector<int> a; // FAIL: reference to 'std' is ambiguous
return 0;
}
To fix this ambiguity over accessing the original std namespace, you'll need to write it as follows:
::std::vector<int> a; // Fully qualified name: Only way to refer to the `::std` namespace
As you can see, it still does not solve the issue and even worse, it adds a huge inconvenience.
Therefore the morality is:
Do not hide an already existing type but create a distinct one instead.
In the same way, do not hide a namespace (by defining the same namespace into an anonymous one --> evil).
(I'm open to any improvement proposal of this answer)
Could you use this kind of solution : Rather than working on std::string, you work on the function that will cause the problem
#include <string>
void test(const std::string& s){
}
// add a new function which use a pointer :
void test (const char* _Nonnull s) {
test(std::string(s));
}
int main()
{
test(NULL);
return 0;
}
Then clang will generate a warning :
1 warning generated.
ASM generation compiler returned: 0
<source>:13:14: warning: null passed to a callee that requires a non-null argument [-Wnonnull]
test(NULL);
see https://godbolt.org/z/PujFor
I would like to modify PierreBdR's exception example of how to make a custom exception so that it is visible to other classes. His example works for me but the exception is visible only inside that class.
I'm using MS Visual Studio 2013 and I'm a C++ newbie encumbered by a Java mentality.
Here is what is in the .hpp file:
struct IllegalArgumentException : public std::exception
{
public: IllegalArgumentException(std::string ss);
public: ~IllegalArgumentException();
const char* IllegalArgumentException::what() { return s.c_str(); }
private: std::string s;
};
Here is part of the .cpp file:
IllegalArgumentException::IllegalArgumentException(std::string ss) : s(ss) {}
IllegalArgumentException::~IllegalArgumentException() {}
const char * IllegalArgumentException::what() { return s.c_str(); }
I'm getting:
error C2011: 'IllegalArgumentExcpetion': 'struct' type redefinition (.hpp file)
Point 1
const char* IllegalArgumentException::what() { return s.c_str(); }
is declared incorrectly if declared inside a class or struct. Since the declaration is being made inside the IllegalArgumentException class, IllegalArgumentException:: is implied and messes with the compiler because the compiler now thinks you are declaring something else. You want
const char* what() { return s.c_str(); }
In addition, the { return s.c_str(); } portion implements the function, so there is no need to implement it in the cpp file.
Point 2
Everything in a struct is public unless declared following the private keyword. This is the opposite of a class where everything is private unless stated otherwise. A class and a struct are pretty much identical other than the difference on default access.
Point 3
In C++ you can declare access level of members in blocks. There is no need to declare the access level of members one at a time.
struct IllegalArgumentException : public std::exception
{
// these are all public by default in a struct
IllegalArgumentException(std::string ss);
~IllegalArgumentException();
const char* IllegalArgumentException::what() { return s.c_str(); }
private: // everything after this is private
std::string s;
int example;
};
or
class IllegalArgumentException : public std::exception
{
public: // these are all private by default in a class and need to be public
IllegalArgumentException(std::string ss);
~IllegalArgumentException();
const char* IllegalArgumentException::what() { return s.c_str(); }
private: // switch back to private
std::string s;
int example;
};
or
class IllegalArgumentException : public std::exception
{
// these are all private by default in a class
std::string s;
int example;
public: // everything after this is public
IllegalArgumentException(std::string ss);
~IllegalArgumentException();
const char* IllegalArgumentException::what() { return s.c_str(); }
};
Point 4
IllegalArgumentException::~IllegalArgumentException() {}
doesn't do anything. It doesn't need to do anything so the Rule of Zero recommends against having a destructor at all. The compiler will create it for you. If you don't have to write it, don't write it because code that doesn't exist has no bugs.
class IllegalArgumentException : public std::exception
{
// these are all private by default
std::string s;
int example;
public: // everything after this is public
IllegalArgumentException(std::string ss);
const char* IllegalArgumentException::what() { return s.c_str(); }
};
Point 5
Stealing from KerrekSB here because it's a point that OP had another question on. Use Include Guards
Include guards prevent a header from being included multiple times in the same translation unit. This is a problem because of bloat and the possibility of the same thing being defined or declared more than once leading to confusion about which is the real one.
A simple header guard:
#ifndef ILLEGALARGUMENTEXCEPTION_H // if we've never seen ILLEGALARGUMENTEXCEPTION_H
// before, do the following
#define ILLEGALARGUMENTEXCEPTION_H // OK we've seen it now!
// all subsequent includes of IllegalArgumentException.h will have seen
// ILLEGALARGUMENTEXCEPTION_H and fail the ifndef, skipping everything
// until it finds the closing #endif
#include <string>
#include <exception>
class IllegalArgumentException : public std::exception
{
// these are all private by default
std::string s;
int example;
public: // everything after this is public
IllegalArgumentException(std::string ss);
const char* IllegalArgumentException::what() { return s.c_str(); }
};
#endif // end of Include Guard
You may also use #pragma once, but be warned that #pragma means non-standard compiler extension. once may not exist for your compiler and if it doesn't, the compiler is allowed to skip the instruction without telling you!
There are many reasons why once is not in the standard, most important is it has unresolved fail cases. Use it with caution.
You mixed up the what() function's declaration and definition. You tried refer to the function with the scope resolution operator (i.e ::). In this case it should be done in the definition (i.e in the .cpp file)
Also the what() function was implemented as an inline function in your .hpp file, which means that you don't need to define it again in the .cpp file. Therefore you got a redefinition of ‘const char* IllegalArgumentException::what() error.
P.S: In C++ class declarations one does not need to specify every attribute/method's access modifier, you can just group them under a single modifier.
.hpp file:
struct IllegalArgumentException : public std::exception
{
public:
IllegalArgumentException(std::string ss);
~IllegalArgumentException();
const char* what() { return s.c_str(); }
private:
std::string s;
};
.cpp file:
IllegalArgumentException::IllegalArgumentException(std::string ss) : s(ss) {}
IllegalArgumentException::~IllegalArgumentException() {}
It seems you are possibly, perhaps indirectly, including the .hpp file more than once?
#include is a fairly primitive way to share code among several .cpp files: it tells the compiler (the preprocessor, specifically) to import the contents of the .hpp right there at that spot in the code. Then in a later pass, the compiler will compile the entire thing as if it is all one file. (There's a whole crazy turing-complete language for that preprocessor step; IMO you should avoid it as much as possible, mostly only using it for the stuff outlined in this note.)
One problem with this approach is that if you end up importing one .hpp file more than once – a very common thing to do, since .hpp files typically include other .hpp files – you will have that code repeated. It's illegal to define a struct or class more than once, so you get the error about "type redefinition".
The solution is to use include guards in every single .hpp file. At the very top, use lines like:
#ifndef SOME_STRING_THAT_UNIQUELY_IDENTIFIES_THIS_HEADER
#define SOME_STRING_THAT_UNIQUELY_IDENTIFIES_THIS_HEADER
Then at the very bottom of the .hpp file:
#endif // SOME_STRING_THAT_UNIQUELY_IDENTIFIES_THIS_HEADER
Those preprocessor directives, #ifndef, #define, etc will remove any text in the middle if the big unique string is already defined. Usually your codebase will establish conventions for that big string, such as encoding the path into it. My company even uses a lint tool to make sure you encoded it correctly.
This ensures that if you #include a .hpp twice, or #include another .hpp that includes an already-included .hpp, you will get the contents of the .hpp file exactly once in the final preprocessor output.
This, and the preprocessor in general, is one of the less charming parts of C++ that really shows its age. Soon the language will be getting a much more modern and pleasant system for sharing interfaces called "modules". In the meantime, each .hpp needs these 3 lines of boilerplate.
I am not sure, but I can comment so...
I think your "what" function is two times implemented:
First in your hpp file and then in the cpp file.
Thanks for taking the time to view my question. I've spent a lot of time looking but can't find a solution to this problem:
I have a class Person with its' respective Header file Person.h. The cpp class is having a hard time understanding what the variables name, age, and iq are.
//Person.cpp
/*
Makes a person.
A person has a name, an age, and an IQ level.
We will create many of these objects within other classes.
*/
#include "Person.h"
Person::Person() //Empty constructor
{
}
Person::Person(string thename, int theage, int theiq)
{
name = thename;
age = theage;
iq = theiq;
}
string getName()
{
return name; //Error: identifier "name" is undefined
}
int getAge()
{
return age; //Error: identifier "age" is undefined
}
int getIq()
{
return iq; //Error: identifier "iq" is undefined
}
void setName(string aName)
{
name = aName; //Error: identifier "name" is undefined
}
void setAge(int aAge)
{
age = aAge; //Error: identifier "age" is undefined
}
void setIq(int aIq)
{
iq = aIq; //Error: identifier "iq" is undefined
}
The Header File
//=================================
// include guard
#ifndef __PERSON_H_INCLUDED__
#define __PERSON_H_INCLUDED__
//=================================
// forward declared dependencies
//=================================
// included dependencies
#include <string> //For the name
//=================================
using namespace std;
class Person
{
public:
Person(); //Default constructor
Person(string thename, int theage, int theiq); //Constructor
string getName();
int getAge();
int getIq();
void setName(int aName);
void setAge(int aAge);
void setIq(int aIq);
private:
string name;
int age, iq;
};
#endif //__PERSON_H_
SURELY I don't have to define the variables inside Person.cpp right? It already knows exactly what variables name, age, and iq are because it saw the header file already. Why can it not understand what those variables are?
If I do, or if there is anything I'm missing, make sure to really spell it out for me. I'm barely an intermediate C++ programmer so I may not understand jargon. Even things like scope, inheritance, and definitions go way over my head.
Thank you for your time.
To which ever part you're getting errors do this:
return type Person::function name(parameters)
For the declaration part of the functions.
For example for the getAge function do this:
int Person::getAge() {
return age;
}
The reason you got errors is because of the following:
First your intention was to define the functions you declared in the Person class.
In the return statement you wanted to return age member of the Person class. But you simply returned age.
The search for age begins inside the function body first. If its not found it is searched in the outer scope. If its still not found age is an unknown identifier.
After you fix it what happens is this:
The Person:: part in the return type Person::function name(parameters) means that look in the scope of the Person class.
Then in the return statement we return age member of the Person class. But this time we're looking inside the scope of the Person class, hence we return the age member and the error is fixed.
You need to change
string getName()
to
string Person::getName()
in the .cpp file. Ditto for the others., The compiler needs to know that this is a part of the class Person.
Your function
string getName()
{
return name; //Error: identifier "name" is undefined
}
is not defining the class member function. Instead you are declaring and defining a (completely different and unrelated) free function. As such, name is undefined within the scope of this function.
On compiling following code I get error "expected unqualified-id before string constant"
In file "Notification_Constants.h"
namespace NOTIFICATION_CONSTANTS
{
#define SERVICE_EMAIL "service#company.com"
}
In file SendEmail.cpp
#include "Notification_Constants.h"
void UserPreferences::get_senders_email(String &_email)
{
_email = NOTIFICATION_CONSTANTS::SERVICE_EMAIL;
}
If i assign like following it works properly, what is the reason for the compilation error.
_email = SERVICE_EMAIL;
There is a similar question but the reason is not mentioned.
String class declaration with relevant methods
class String
{
public:
String();
String(const String& src);
String(const char *new_str);
String& operator=(const String& src);
String& operator=(const char *new_str);
};
First, you should put quotation marks around the email address:
#define SERVICE_EMAIL "service#company.com"
Second, you should not use #define at all. Use a const variable instead:
const String SERVICE_EMAIL = "service#company.com";
#defines are type unsafe, have no scope and are generally evil.
Last, you may want to consider using std::string instead of your String class.
Update:
The problem is that the preprocessor #defines are nothing more than text substitutions. When the preprocessor is done, your compiler will see
_email = NOTIFICATION_CONSTANTS::"service#company.com";
There is no string constant in that namespace. SERVICE_EMAIL is not an identifier of any kind - it is just an indication to the preprocessor to substitute any occurrence of SERVICE_EMAIL with "service#company.com".
The solution is to remove the namespace qualifier:
_email = SERVICE_EMAIL;
Better solution:
If you do not have access to the #define, you should wrap it in a header file, if possible:
#include "Notification_Constants.h"
namespace NOTIFICATION_CONSTANTS {
const String REAL_SERVICE_EMAIL = SERVICE_EMAIL;
}
and then use NOTIFICATION_CONSTANTS::REAL_SERVICE_EMAIL instead, which has scope, is a type, is a proper member of the namespace, and so on.
The problem is, I think since I don't know the String type, is that SERVICE_EMAIL should be a string literal:
#define SERVICE_EMAIL "service#company.com"
but then, it should fail even in the latter solution. Maybe your code snippet doesn't show the real problem.
#define SERVICE_EMAIL "service#company.com"
What's the type of service#company.com?
I think you wish to use a string to store an email address.
Try:
#define SERVICE_EMAIL "service#company.com"