Segmentation fault in conversion operator (reference to member) - c++

Why is this causing segmentation fault?
#include <iostream>
struct A
{
std::string str;
A(std::string const& pstr) : str(pstr)
{}
operator std::string const&() const { return str; }
};
bool operator==(A const& a, A const& b)
{ return std::string(a) == b; }
int main()
{
A a1("hola"), a2("adios");
std::cout << (a1 == a2) << std::endl;
return 0;
}
After all, the member str is still alive when doing the conversion.
http://coliru.stacked-crooked.com/a/e7453471bc1af93e

You have an recursive call to your operator==. Your constructor of A defines an implicit cast of string to A. To not allow that, add explicit to the constructor, but then you are missing a operator== for string and A;

Just edited your code and it worked for me:
return std::string(a) == std::string(b);

Related

Overloading the operator=? c++

I having a trouble trying to insert an object from a class that I created to a char. I create a class name Element as part of a bigger program, but when I try to overloading operator= so that i can get in char variable the char I got in the Element obj nothing work...
Element.h
class Element {
private:
char val;
public:
Element();
Element(char newVal); //check input - throw execption
~Element();
friend ostream& operator<<(ostream& os, const Element& obj);
void setElement(char newVal);
char getElement();
void operator= (const Element newVal);
void operator= (char newVal);
};
Element.cpp
#include "Element.h"
Element::Element()
{
val ='.';
}
Element::Element(char newVal)
{
if (newVal!='X' && newVal!='O'&& newVal!='.'){
inputExecption error;
error.what();
} else{
val=newVal;
}
}
Element::~Element()
{
}
void Element::setElement(char newVal)
{
if (newVal!='X' && newVal!='O'&& newVal!='.'){
inputExecption error;
error.what();
} else{
val=newVal;
}
}
char Element::getElement()
{
return val;
}
ostream& operator<<(ostream& os, const Element& obj)
{
return os << obj.val;
}
void Element::operator= (const Element Value){
val = Value.val;
}
void Element::operator= (char newVal){
if(val != 'X' && val != 'O'){
inputExecption a;
a.what();
}
val = newVal;
}
So as I said, what i'm trying to do is:
Element x='X';
char c = x; //(c=x.val)
cout<<c<<endl;//Will print X
thx! :)
In other words you're trying to convert an object of type Element to an object of type char. You can use a conversion operator for this:
class Element {
// ...
operator char() const { return val; }
};
The assignment operator only works when an instance of Element is used on the left hand side of the assignment.
IMHO, writing an implicit conversion operator (as 0x499602D2 suggested) is not the best idea.
For example, assume you have two separate file something like this:
//File char_utils.hh
#include <iostream>
void accept(char character) { std::cout <<"character: " <<character <<'\n'; }
//File elements_utils.hh
#include <iostream>
void accept(Element const& element) {
std::cout <<"element.getVal(): " <<element.getVal() <<'\n';
}
Then, depending on what you include in your implementation file (char_utils.hh or elements_utils.hh) you will get different behaviour, which may lead to many subtle bugs and/or interesting behaviours. ;)
This can be overcome by declaring conversion operator explicit, i.e.,
explicit operator char() const { return val; }
In such a case, you just need to:
Element e{'x'};
char c = static_cast<char>(e);
which shows the intent more clearly.
However, why do you need using an implicit conversion at all? Especially when you can use Element::getElement()? And if I may suggest, I would use different namin, e.g., Element::getValue(). Element::getElement() is very confusing.
Further reading: https://stackoverflow.com/a/16615725/1877420

Compare two objects in vector iteration C++

How to implement the comparison function in this case?
void remove(const Object1 &object1) {
for(auto &object2 : objectVector) {
if(object1 == object2) {
/*....... */
}
}
}
You are asking 2 questions:
How can objects be made comparable:
By implementing operator== for the class. Be sure you override operator != then too.
As a member function:
bool Object1::operator ==(const Object1 &b) const
{
// return true if *this equals b;
}
Or as a free function:
bool operator ==(const Object1 &a, const Object1 &b)
How can objects with a given value be removed from a vector:
The easiest way is to use std::remove:
objectVector.erase(std::remove(objectVector.begin(), objectVector.end(), object1), objectVector.end());
You can remove objects also while iterating through the vector, but you have to keep in mind that the vector iterator is invalidated then. You may not further iterate on the vector then.
An object of your class can contain different types and number of members so let's say that you have a class A:
class A{
int x,
float y;
char* z;
};
And you have two instances:
A a1;
A a2;
To compare:
if(a1 == a2) // compile-time error
;// DoSomeThing
Above you get the error because the compiler doesn't know which fields will be compared against each other. The solution is to overload the equals operator "==" to work on objects of your class.
class Student{
public:
Student(std::string, int age);
std::string getName()const;
int getAge()const;
bool operator == (const Student&);
private:
std::string name;
int age;
};
Student::Student(std::string str, int x) :
name(str), age(x){
}
bool Student::operator == (const Student& rhs){
return age == rhs.age;
}
std::string Student::getName()const{
return name;
}
int Student::getAge()const{
return age;
}
int main(){
Student a("Alpha", 77);
Student b("Beta", 49);
if(a == b)
std::cout << a.getName() << " is the same age as " <<
b.getName() << std::endl;
cout << endl << endl;
return 0;
}
Now the compiler knows how to compare objects of your class and know what the equals operator compares on your ojects members.
if object is a class you can override the operator == in the class as a friend function, or you can implement your own function bool isEqual(Object1 o1, Object1 o2) { if(something) return true; return false; }

C++ return value from a class-member function

I can't understand why a.funct() can be the left operand of the assignment operator even if funct() is not returning a l-value reference.
class A
{
public:
A funct () {A x; return x;}
};
int main ()
{
A a,b; a.funct()=b;
}
In the auto generated methods for the class, there is
A& operator = (const A&);
which make a.funct() = b legal.
To forbid affectation to rvalue, you may, since C++11, write and implement
A& operator = (const A&) &; // Note the last &
so assignation would only work for lvalue.
In the code, funct should return a variable that can be assigned to.
Note that the code in funct is very dangerous too if it were to be returned by reference; the local variable x will go out of scope once the function ends and the variable returned will cause undefined behaviour as its destructor will have been called.
Your assumption is wrong. Your code is perfectly valid.
Try this code:
#include <string>
#include <iostream>
class A
{
std::string m_name;
public:
A(const std::string& name) :m_name(name) {}
A funct() { A x("intern"); return x; }
A& operator=(const A& a)
{
m_name += a.m_name;
return *this;
}
void print() { std::cout << m_name << std::endl; }
};
int main()
{
A a("A"), b("B"); (a.funct() = b).print();//prints "internB"
}

Trouble with defining my own operator...

I'm just toying around to watch how defining operators work. The following code gives me an error about "No candidate functions found".
Any criticism other than that of the root cause is welcome, too. Thanks!
#include <iostream>
using std::cout; using std::cin; using std::endl;
using std::string;
class SomeClass {
public:
SomeClass(int newNum, string newString) { num=newNum; str = newString; }
SomeClass& operator=(const SomeClass& rh) {
string newVal(rh.getStr());
str = newVal;
}
void setStr(string newString) { str = newString; }
const string getStr() { return str; }
string toString() { return str+str; }
private:
string str;
int num;
};
int main() {
SomeClass a(5, "five");
SomeClass b(3, "three");
cout << a.toString() << endl << b.toString() << endl;
a=b;
cout << a.toString() << endl << b.toString() << endl;
}
const string getStr() { return str; }
should be
const string& getStr() const { return str; }
Otherwise you cannot call a non-const function on a const parameter of
SomeClass& operator=(const SomeClass& rh)
Note that private, public and protected visibility is at class level, not instance level. So there is no need for a getStr() function. You could write:
SomeClass& operator=(const SomeClass& rh) {
this->str = rh.str;
return *this;
}
Everything looks fine so far except that you've not included
#include <string>
You need to include this as well.
Oh I also saw that you're not returning anything from the function:
SomeClass& operator=(const SomeClass& rh) {
string newVal(rh.getStr());
str = newVal;
return *this; //DO THIS AS WELL
}
And also, rh is a const object in this function and using it, you're calling getStr() which is a non-const function which is causing the problem. So the fix is this:
const string getStr() const { return str; }
// ^^^^^ make the function const!
And alternatively, you could've written your operator= as follows:
SomeClass& operator=(const SomeClass& rh) {
str = rh.str; //no need to create a local (temporary) variable!
return *this; //DO THIS AS WELL
}
I think its better solution!
You just need to change
const string getStr() { return str; }
to
const string getStr() const { return str; } //the 2nd const make getStr() a const member function
^^^^
This is because const object can only call const member function and you were trying to doing this:
SomeClass& operator=(const SomeClass& rh) { //here you declared rh to be const
//so in order to call getStr() from rh, you need declare getStr function to be const
string newVal(rh.getStr());
str = newVal;
return *this;
}
So your class could simply look like this:
class SomeClass {
public:
SomeClass(int newNum, string newString):num(newNum), str(newString) {/* Empty */}
SomeClass& operator=(const SomeClass& rh) {
str=rh.str;
return *this;
}
string toString() { return str+str; }
private:
string str;
int num;
};

C++ class conversion possible?

I have the following code:
class B {
public:
B(const std::string& str):m_str(str) { }
B(const B& b):m_str(b.m_str) { }
B& operator=(const B& b) { m_str = b.m_str; return *this; }
private:
std::string m_str;
};
main()
{
std::string a = "abc";
B b(a);
}
class B belongs to the client. I can't change it and I may not even know its specific name ("B" is simply an example); all I know is there's a client class that accepts a std::string for its constructor. Now I want to change the type of "a" in main() from std::string to A, as defined below:
class A {
public:
A(const std::string& str):m_str(str) { }
A(const char *str):m_str(str) { }
A(const A& a):m_str(a.m_str) { }
A& operator=(const A& a) { m_str = a.m_str; return *this; }
private:
std::string m_str;
};
So now I have a new main():
main()
{
A a = "abc";
B b(a);
}
This can't compile properly as it is. Is there anything I can do without changing the new main()? I can't change class B, and class A should not reference class B in any way.
Thanks!
add an cast operator
class A {
public:
....
operator const std::string()
{
return m_str;
}
Add user-defined conversion function as:
class A
{
public:
//other code
operator std::string()
{
return m_str;
}
//...
};
This allows you write these:
B b(a); //which is what you want
std::string s = a; //this is also okay;
void f(std::string s) {}
f(a); //a converts into std::string, by calling user-defined conversion function
However you cannot write this:
const A ca("hi");
std::string s = ca; //error
Its because ca is a const object which cannot invoke non-const user-defined conversion function.
Note the user-defined conversion function returns the string by value which means it returns a copy of the original string. So you may want to avoid this by defining it as:
operator const std::string &() const
{
return m_str;
}
Now, with this you can write this:
const A ca("hi");
std::string s = ca; //ok
A a("hi");
std::string s = a; //ok
How about
int main() //note the correct declaration of main
{
A a = "abc";
B b(a.GetString()); //GetString returns m_str;
}
By the way, all your definitions of copy constructors and copy-assignment operators coincide with the definitions the compiler would have auto-generated for you.
Edit
I just noticed your constraint that main() should not change. In this case you can define a conversion function from A to string (but it can be dangerous, note).
class A
{
...
operator std::string() const {return m_str; }
};
Add this to class A:
operator std::string () { return m_str; }