C++ Need Help for Class Declaration in Header - c++

I get stuck when trying to understand following code.
class V8_EXPORT Utf8Value {
public:
explicit Utf8Value(Local<v8::Value> obj);
~Utf8Value();
char* operator*() { return str_; }
const char* operator*() const { return str_; }
int length() const { return length_; }
private:
char* str_;
int length_;
Utf8Value(const Utf8Value&);
void operator=(const Utf8Value&);
};
Line: "~Utf8Value();"
When I checked the cpp file, it contains only one line:
String::Utf8Value::~Utf8Value() {
i::DeleteArray(str_);
}
Does it mean that the function is to delete the char* str_? Is there any reason why got a ~ before the function name? Can I rename it to other names instead of ~Utf8Value?
Line: const char* operator*() const { return str_; }
What does it do? Why there is a * after function name?
My understanding of const is that the fucntion/variable will never change, but what does the second const after brackets mean?
Line: Utf8Value(const Utf8Value&);
Is it another constructor like the first line explicit Utf8Value(Local<v8::Value> obj); ?
Line: void operator=(const Utf8Value&);
I have no idea what this line is trying to do.
Can anyone help me with this? Any help would be much appreciated!
Thank you!!

It seem you do not know the C++ syntax well before you try to read some bigger project source code.
To your question:
A function start with '~' in class declaration (scope) is the Destroy function of a class object which call automatically when the object is die or deleted. In this case, An object of Utf8Value (let us call it object at next) have been hold a str_ pointing to somewhere that need to free when the host being destroying. Get to give, give to get. Finally, you can not rename it.
This line declares a behavior when treat this object as a char* string. What does it did this here call operator override in C++ and most operator can be designed as what you want, like arithmetic, compare, shift, etc. That is a very peculiar characteristics of C++. For the 'const' function, it means this function will not change something in this object.
Yes. But since it is declared in the private scope, it can NOT be called out of the object or another constructor. Generally speaking, it is designed to forbidding construct an object in a way that designer does not want.
It works like question 3 while trying to stop constructing an object from value assignment.

Related

Why did I get the: "Attempting to reference a deleted function" error after adding a vector with unique pointers to my header file?

To learn C++ I am programming a game. In this game, there can be two players. Those players, are able to connect to each other with sockets. After adding a vector with unique pointers to the player header I got the error: "Error C2280 'std::unique_ptr>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function". Same error goes for the Building vectors.
To give a more clear view of what the problem is, I have set my header file in a code block below:
class Player {
public:
Player() {}
Player(const std::string& name) : _name {name} {}
std::string get_name() const { return _name; }
void set_name(const std::string & new_name) { _name = new_name; }
const bool compare_name(const std::string & name) const;
void set_coins(const int coins);
const int get_coins();
void set_king(const bool king);
const bool get_king();
private:
std::string _name;
int _coins;
bool _is_king;
std::vector<std::unique_ptr<Building>> _buildings;
std::vector<std::unique_ptr<Building>> _placed_buildings;
std::vector<std::unique_ptr<Character>> _characters;
};
The last three vectors are the vectors that I was trying to add to my header file. I have added them to another class in a similar way. And in that class, it did not lead to an error. But in my player header file, it does. Could you help me to solve/clarify this error?
All help will be appreciated.
Edit: An attempt to explain why this question is not a duplicate.
It might be a duplicate but for now, as far as I can see, is that in the question: "Why can I not push_back a unique_ptr into a vector?" someone is trying to call the push_back function without using the std::move in the push_back. At the moment I am not trying to put values inside my vector. What I want is a vector of unique pointers inside my header. So I am not trying to fill the vectors with elements yet. Therefore I tend to think that it is not possible to make use of std::move for the building and character vectors yet. I know this error often occurs when not calling the std::move function because I have looked at the other StackOverflow posts. But none of them seems to have the right answer to my question. Because the answer to most of them is: use "std::move" or use a "default constructor" and that did not solve my problem.
My expectation is that it has something to do with player being defined as a shared_ptr and player is the container for the vectors could that be a part of the problem?
If there is no copy constructor defined in a class, a compiler will provide a default one (along with the assignment operator). This default copy constructor will attempt to copy class members, including a vector of unique pointers in this case.
One has to make the class explicitly non copyable:
Player(const Player&) = delete;
Player& operator =(const Player&) = delete;
Most probably, you are copying Player object somewhere which is by default element copying of every field. You can't copy a vector of unique pointers

Object has type qualifiers that prevent match (function overload not found)

I have a simple class, intended to convert integers to byte arrays.
class mc_int {
private:
int val; //actual int
public:
int value(); //Returns value
int value(int); //Changes and returns value
mc_int(); //Default constructor
mc_int(int);//Create from int
void asBytes(char*); //generate byte array
mc_int& operator=(int);
mc_int& operator=(const mc_int&);
bool endianity; //true for little
};
For conversion and simpler usage, I decided to add operator= methods. But I think my implementation of mc_int& operator=(const mc_int&); is incorrect.
mc_int& mc_int::operator=(const mc_int& other) {
val = other.value();
// |-------->Error: No instance of overloaded function matches the argument list and object (object has type quelifiers that prevent the match)
}
What could this be? I tried to use other->value(), but that was wrong too.
Your member function value() is not a const function, which means it has the right to modify the members, and cannot be called on const objects. Since I assume you meant it to be read only, change it to int value() const;. Then you can call it on const instances of mc_int, and it guarantees you don't accidentally change any members.
When it says "Object has type qualifiers blah blah", that means an object has too many const or volatile qualifiers to access a function.
Also, since you posted a summary of an error, I assume you're using visual studio. Visual Studio shows summaries of errors in the "Error" window. Go to View->Output to see the full errors in their terrible detail, which should have told you which variable was the problem, and that it couldn't call that function because of it's constness.
Try changing:
int value(); //Returns value
To:
int value() const; //Returns value
In this overloaded operator=, other is a const reference. You can only call member functions that are marked const on this object. Since the value() function just returns val and doesn't modify the object, it should be marked as const:
int value() const;
This says that this function won't modify the state of the object and can therefore be called on const objects.

const and no const methods in c++?

I have a program and many of its classes have some operators and methods with the keyword const like the followings:
operator const char* () const;
operator char* ();
void Save(const char *name) const;
void Load(const char *name);
First: what does it mean const at the end of the method declaration?, is it the same like putting it at the beginning?
Second: Why would be a const version and a no const version of operator() needed?
Thanks in advance.
First: what does it mean const at the end of the method declaration?, is it the same like putting it at the beginning?
No. A const at the end means that the method may be called on objects that are declared const. A const at the beginning means that the returned value is const.
Second: Why would be a const version and a no const version of operator() needed?
The non-const version returns a char* which is not const. By modifying this char* you could then in fact modify the object (assuming the char* is a member of the object).
Since this is not allowed for const objects, there's an overload of operator() for const objects, so that a const char* is returned, so the object can't be modified through it.
'const' at the end tells the compiler that this method does not change any member variables - that it is safe to call this method on const instances. So, Save could be called on a const instance, since it won't change that instance. Load on the other hand, will change the instance so can't be used on const instances.
The const version of operator() passes back a const pointer, guaranteeing the buffer passed back won't change. Presumably that's a pointer into a instance variable of the class. For non-const instances, the other operator() passes back a non-const pointer. It would have to be a pointer to some memory that even if written to, wouldn't change the contents of the instance.
Also, look up the 'mutable' keyword sometime. Understanding that will help you understand this idea of const-correctness.
Member function constness. It means the function can not(*) modify any of your member variables. It's like putting a const in front of all your member variables for this one function call. It's a good guarantee for the clients of your class and may also aid in compiler optimisations.
(*) - see also the keyword mutable.
Putting const at the end of a method declaration is stating that the object itself, or this, is const instead of the return type.
C++ allows methods to be overloaded on const for complicated reasons. Not enough space to go into full detail here. But here are a couple of short ones.
Ocassionally there is value, or flat necessity, in having a method behave differently when it is called from a const type. The most straight forward example is when you want to return a const value from a const method and a non-const value from a normal method.
Whether or not this is const dramatically changes the binding of the internal method. To the point that it would essentially become two different method bodies. Hence it makes sense to break it up into 2 different methods.
One note in addition to the other answers: there is no operator() in your example.
operator const char* () const;
operator char* ();
are conversion operators, which mean that objects of the class can be implicitly converted to C-style strings, like
void f(const MyClass& x, MyClass& y) {
const char* x_str = x;
char* y_str = y;
}
A declaration and usage of operator(), which means you can use an object of the class type sort of like a function, would look like:
class MyClass {
public:
const char* operator() (int x, int y) const;
// ...
};
void g(const MyClass& obj) {
const char* result = obj(3, 4);
}
If you're looking for a great resource on C++ (including tips on using const correctly) try "Effective C++".
A useful site about this: JRiddel.org
In C++ when you declare a method const by putting it AFTER the method signature you are asserting that "This method will not change any non-mutable instance variables in the object it is being called on."
The const before the return value (e.g. the const in: operator const char*...") is declaring that it only returns a variable pointer to a const char*. (You may not change the contents of the char* but you can re-assign the pointer.) If you wrote "const char* const ..." it would be a constant pointer to constant characters. (The const comes after the star).
The multiple versions are useful so the compiler can understand this:
const char* my_const_var = <object_name>();
char* my_var = <object_name>();
Chris
You should refer to the "HIGH·INTEGRITY C++ CODING STANDARD MANUAL" for knowing when it is recommended to use the const modifier for class members:
High Integrity CPP Rule 3.1.8: Declare 'const' any class member function that does not modify the externally visible state of the object. (QACPP 4211, 4214)
Justification: Although the language enforces bitwise const correctness, const correctness should be thought of as logical, not bitwise. A member function should be declared const if it is impossible for a client to determine whether the object has changed as a result of calling that function. The 'mutable' keyword can be used to declare member data which can be modified in const functions, this should only be used where the member data does not affect the externally visible state of the object.
class C
{
public:
const C& foo() { return * this; } // should be declared const
const int& getData() { return m_i; } // should be declared const
int bar() const { return m_mi; } // ok to declare const
private:
int m_i;
mutable int m_mi;
};
Reference Effective C++ Item 21;Industrial Strength C++ 7.13;
Const at the beginning applies to the return value. Const at the end applies to the method itself. When you declare a method as "const" you are saying that you have no intention of modifying any of the member variables of the class in the method. The compiler will even do some basic checks to make sure that the method doesn't modify member variables. The const in the return value prevents the caller from modifying the value that is returned. This can be useful when you return pointers or references to data managed by the class. This is often done to avoid returning copies of complex data which could be expensive at run time.
The reason you have two different operators is that the "const" version returns a const pointer to what is probably data internal to the class. If the instance of the class is const, then chances are you want the data being return should also be const. The "non-const" version just provides a method that returns a modifiable return value when the caller has a non-const instance of the class.

Correct usage(s) of const_cast<>

As a common rule, it is very often considered a bad practice to use const_cast<>() in C++ code as it reveals (most of the time) a flaw in the design.
While I totally agree with this, I however wonder what are the cases were using const_cast<>() is ok and the only solution.
Could you guys please give me some examples you know/you encountered ?
Thank you very much.
it is pretty much designed to be only used with legacy APIs that are not const correct i.e. with a function you can't change that has non const interface but doesn't actually mutate anything on the interface
Like others have said, its primary purpose is to remove const from objects in order to pass to non-const correct functions you know won't modify the argument.
There is a trick (by Meyers?) to avoid code duplication, and it goes like this:
struct foo
{
const return_type& get(void) const
{
// fancy pants code that you definitely
// don't want to repeat
return theValue; // and got it
}
return_type& get(void)
{
// well-defined: Add const to *this,
// call the const version, then
// const-cast to remove const (because
// *this is non-const, this is ok)
return const_cast<return_type&>(static_cast<const foo&>(*this).get());
}
};
const_cast is also used to remove volatile modifiers, as put into practice in this (controversed) article:
http://www.drdobbs.com/184403766
I agree with your statement that its normal use is because you need to hide a 'design flaw'.
IME one of the typical usage scenarios is when you try to interface C++ to existing C code. A lot of existing C code takes C strings as char * even when the string is not modified whereas they're usually represented as something that converts to a const char * in C++. That's an impedance mismatch between the two languages that you would normally solve by using a const_cast. Of course you'd better be very sure that the code you're interfacing with doesn't get any cute ideas about modifying the data that's being passed in.
I would say that it's a code smells in newly written code, but for interfacing with older C and C++ code, it's an necessary evil. That said, I would be extremely wary of code that requires const_cast for any non-POD objects as that is normally a problem that should be solved at the design level and not the code level.
One legitimate use (in my opinion) is with std::set iterators. They are always const, in order to prevent changing the key used in the set. Changing the key would break the internal structure of the set and cause undefined behavior.
However, as long as the key doesn't change it's safe to change other data in the object.
Let's say you have an std::set like this:
std::set<MyObject> some_set;
And a class like this:
class MyObject {
public:
MyObject(const std::string &key)
: key_(key) {}
bool operator<(const MyObject &other) const {
return key_ < other.key_;
}
private:
// ...
// <some other data>
// ...
const std::string key_;
};
In the above example, the key is already const, so even if you modify the object, you cannot break the internal structure of the set.
Normally you can only get a const reference out of a set iterator:
const MyObject &object = *some_set_iterator;
But since the key is const, it's safe to const_cast the dereferenced iterator:
MyObject &object = const_cast<MyObject &>(*some_set_iterator);
One very legitimate use of this is when you have both a const and non const api (for const and non const objects respectively) as in
class Bar {
const SomeType& foo() const;
SomeType& foo();
}
Then since we don't want to duplicate the code in both functions we often use
class Bar {
SomeType& foo() {
//Actual implementation
}
const SomeType& foo() const {
return const_cast<Bar*>(this)->foo();
}
};
This is of course assuming that foo does not do something that violates the const semantics.
Yes of course, when your calling code that you can't modify and isn't const correct. It should be noted that you should only use it with calls to functions that you know for certain won't modify your data!
There is an example of const_cast usage in c++ primer(5th edition) book.
Below function returns reference to const string
// return a reference to the shorter of two strings
const string &shorterString(const string &s1, const string
&s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}
The book then mentions the case when we want a non const reference.
We can call the function on a pair of nonconst string arguments, but
we’ll get a reference to a const string as the result. We might want
to have a version of shorterString that, when given nonconst
arguments, would yield a plain reference. We can write this version of
our function using a const_cast:
string &shorterString(string &s1, string &s2)
{
auto &r = shorterString(const_cast<const string&>(s1),
const_cast<const string&>(s2));
return const_cast<string&>(r);
}
This version calls the const version of shorterString by casting its
arguments to references to const. That function returns a reference to
a const string, which we know is bound to one of our original,
nonconst arguments. Therefore, we know it is safe to cast that string
back to a plain string& in the return.
According to the book, it should be used if we know it is safe to cast.

C++ Compiler Error: No matching function for call

Look at the following code. What is wrong with it? The compiler gives the this error:
In copy constructor person::person(person&)':
No matching function for call toperson::copy(char*&, char*&)'
candidates are: void person::copy(char*&, const char*&) "
Here is the code:
class person
{
public:
person();
person(person &);
private:
void copy(char*&,const char*&);
char* name, *fathername,* address;
};
void person::copy( char*& n, const char*& p)
{
int result;
result=strcmp(n,p);
if(result!=0)
{
n=new char[strlen(p)+1];
strcpy(n,p);
n[strlen(p)]='\0';
}
}
person::person(person &object)
{
copy(name,object.name);
copy(fathername,object.fathername);
copy(address, object.address);
}
From the answers to this Question what I understood up until now is given by:
the compiler does not allow to convert a reference to a constant reference because references are already constant. They can't point to a different memory location like pointer. Am I right?
Wouldn't this be nicer?
class person
{
private:
std::string name;
std::string fathername
std::string address;
};
// constructor and copy constructor autogenerated!
It's more "C++" this way ;).
Unless you are planning on changing the pointers you should not pass the references to the pointers:
Change:
void person::copy( char*& n, const char*& p)
to
void person::copy( char* n, const char* p)
This is because p is a reference to a particular type.
The object you passed is not the exact type and becuase it is a reference their is no way to convert it.
The change I suggested above allows for a "pointer to const char" (p) thus allowing read only access to elements via 'p'. Now a "pointer to char" allows read/write access to the data so converting this to "pointer to const char" is allowed because we are just limiting the allowed behavior.
There are a whole set of other problems with the code you posted.
Do you want us to list them?
I don't do NOW. I do on my schedule.
Problems:
1: You leak on each call to copy:
if(result!=0)
{
n=new char[strlen(p)+1]; // What happned to the old n?
2: The default assignment operator is used.
person a;
person b;
a = b; // a.name == b.name etc all point at the same memory location.
// Though because you do not delete anything in the destructor
// it is technically not an issue yet.
3: You done delete the allocated members in the destructor.
{
person a;
} // A destructor called. You leak all the member here.
4: strcpy() already copies the terminating '\0' character.
5: if the call to new throws an exception. You will leak memory.
copy(name,object.name);
copy(fathername,object.fathername); // If new throws in here.
// Then the this.name will be leaked.
Doing this correctly using C-String is so hard that even a C++ expert would have problems doing this correctly. Thats why C++ experts would use std::string rather than a C-String. If you must use C-Strings then you should wrap your C-String in another class to protect it from probelms with exceptions.
Change
person::person(person &object)
to
person::person(const person &object)
for starters...
The compiler is telling you the problem - change your signature to accept 2 char* pointers (rather than 1 const char*) and it should compile.
The issue is really due ot the use of the reference - if you had created a copy method that simply took 2 char* pointers (not references) then the compiler will automatically recognise the conversion from char* to const char* and use the method. As you only have a method that accepts a reference to a different type it cannot do that automatically.
I'm feeling generous, so here is a corrected version of your code:
class person
{
public:
person();
person(const person &);
~person();
private:
void copy(char*&, // Do you understand purpose of '&' here?
const char*);
char* name;
char* fathername;
char* address;
};
person::person()
: name(NULL),
fathername(NULL),
address(NULL)
{
}
person::~person()
{
delete[] name;
delete[] fathername;
delete[] address;
}
void person::copy( char*& n, // The '&' is required because the contents of `n` are changed.
const char* p)
{
delete[] n;
n = NULL; // Here is one place where contents of `n` are changed.
if (p)
{
n = new char [strlen(p) + sizeof('\0')]; // Another content changing location.
strcpy(n, p);
n[strlen(p)]='\0';
}
}
person::person(const person& object)
{
copy(name,object.name);
copy(fathername,object.fathername);
copy(address, object.address);
}
Can you identify the flaws or safety items still lurking?
As others are saying, you shouldn't pass the char pointer by reference if you are not going to modify it.
The problem is that the reference is non-const and therefore doesn't bind to temporaries. Therefore the passed variable's type must match exactly. Near matches that would involve an implicit cast are not acceptable, because the result of an implicit cast is a temporary.
Const references, on the other hand, can be bound to temporaries.
void non_constant(int&);
void constant(const int&);
int main()
{
int i = 0;
unsigned u = 0;
non_constant(i);
//non_constant(u); //ERROR: not an int
//non_constant(10); //ERROR: literals are temporaries
constant(i);
constant(u); //OK, unsigned implicitly cast to int
constant(10); //OK, literals bind to const references
}
So, if you wanted badly to keep the reference in the argument:
void person::copy( char*& n, const char* const& p)
This is VERY (!) poor design. This code is buggy and VERY (!) hard to understand and maintain.
This question is continuation for this question: C++ classes , Object oriented programming.
Now you struggling with symptoms, not with real problem. And real problem is to think in C++ terms not in C (if you want to became C++ object-oriented programmer).
Valid C++ code (C++, not C with classes) here:
#include <string>
class person
{
public:
person();
private:
std::string name, fathername, address;
};
Thats all. All other things (including copy contstructor) C++ compiler generates for you (as well effective as you own manual implementation)! This much simpler, much clearer, easier to maintain and understand, and first of all: bug free;). And this is true C++ code.
Others have already correctly answered your question, but it seems you didn't understand it so far, so I will try to make it as clear as possible for you.
void person::copy( char*& n, const char*& p)
This function expects as the second argument a non-const reference to a const pointer (and not a const reference to a pointer as you might think!).
When you try to call this function passing as the second argument a pointer (not a const pointer) the compiler is unable to create a reference for it, simply because it expects to bind a reference to a const pointer and it is not allowed to implicitly cast the pointer to a const pointer, since non-const references may not bind to rvalues (temporary values).
If you want the function to expect a const reference to a const pointer, you have to change its signature as shown below:
void person::copy( char*& n, const char* const& p)
Here it is important to understant that the compiler implicitly casts the provided pointer to a const pointer before binding the reference, which is allowed in this case, since a const reference may bind both to rvalues and lvalues.
Similarly, if you want the function to expect a const reference to a pointer, which was probably your original intention, then the signature should be as shown bellow:
void person::copy( char*& n, char* const& p)
Here the compiler doesn't have to implicitly cast anything, since the provided argument already matches the type the reference expects to bind.
I hope I made it clear and detailed for you and that you correctly understood what caused the problem, which is indeed important, but nonetheless, I would strongly advice you not to write your code like this, but instead to follow the suggestions given by the others.
Others pointed that you should replace reference with pointer.
Here are a few other but related comments:
If you define copy constructor, define assignment operator too. They should go along together, in most cases.
It's a good practice to declare single argument constructor as explicit.
Naming objects as object is a bad convention and may lead to confusions. It's abvious every instance of type person is an object. Use more meaningful names, like person(const person& other); or person(const person& rhs); // after right-hand-side
Use std::string. If you are programming in C++, there is no
rational reason to not to use std::string and juggle C-strings instead.
Finally, take care of exception safety, follow best practices like copying oprations implemented in terms of non-throwing swap operation. See article Exception-Safe Class Design, Part 1: Copy Assignment by Herb Sutter