Make a pointer on an object that has a reference member? - c++

I'm a student beginner in C++ (but yet have few hours on C), and I'm actually having a problem to use a pointer on my object. I really tried to find infos on the web, but it was pointless (pointless-pointer, do you get it ?!). So I try my luck here.
This code compiles now ! My apologies to all of you that try the code before that. Compiled with :
g++ -Wall -o exec main.cc
#include <iostream>
#include <vector>
//all the includes here
using namespace std;
class ExpLog
{
public:
virtual string toString() const=0;
//virtual int evaluate() const=0;
};
class Atom : public ExpLog
{
protected:
int value;
public:
Atom():value(0){}
string toString() const
{
return "a";//definition doesn't matter here
}
};
class ExpNot : public ExpLog
{
protected:
const ExpLog& opd;
public:
ExpNot(const Atom& a):opd(a){}
string toString() const
{
return "NOT"+opd.toString();
}
};
const ExpLog *my_function(vector<Atom> const& vect_atom, int i)
{
if(i>= vect_atom.size()) return NULL;
const Atom *a = &vect_atom[i] ;
if(i>0)
return a;
else{
ExpNot *n;
n = new ExpNot(*a);
cout<<n->toString()<<endl; //This line leads to a seg:fault
return n;
}
}
int main()
{
int i=-2;
vector<Atom> vect_atom(3);
my_function(vect_atom, i);
}

As others have said, this code snippet(s) does not compile in its current form. However, I'm willing to guess the problem is not in the line you have indicated, but the line
const Atom *a = &vect_atom[i]
If i > vect_atom.size() then this will point outside of the vector. Try adding a check for this just like you have a check for i < 0. If that check does match, then search up the for the root cause: the caller that is passing an invalid index.

Related

Returning different data types from a function in c++

I am writing some kind of buffer parser that takes vector of unsigned char bytes as an input,for example
Datatype getvalue(vector<unsigned char> buffer)
{
// compute value
If vector contains 2 bytes then unsigned int will be returned
If vector contains 4 bytes then unsigned long will be returned
If 12 bytes then date time will
be returns
return value;
}
You cannot do this.
A function can only return one type. You could use some sort of type erasure (std::variant/std::any and others) but as you are bound to C++11, you can resort to the following: Instead of returning the value from the function pass it to a function...
struct Consumer {
void operator()(int x) { ... }
void operator()(float x) { ... }
void operator()(time_t t) { ... }
};
void getValue(Consumer& c,vector<unsigned char> buffer) {
if (...) {
int data;
c(data);
} else if (...) {
float data;
c(data);
} else if (...) {
time_t data;
c(data);
}
}
I will store these values in a vector and that do some computation on each value and then will concat thses values to generate an output string
A vector can only store int or float, so we are back at step zero. However, to add them to a string all you need is a stringstream:
void getValue(std::stringstream& s,vector<unsigned char> buffer) {
if (...) {
int data;
s << data;
} else if (...) {
float data;
s << data;
} else if (...) {
time_t data;
s << data;
}
}
You might want to use some tagged union type.
A C++ function has one return type, not several of them.
In C++17 consider using the std::variant template.
Or code your own implementation, using some union in your class. Then follow the C++ rule of five (even in C++11).
Read a good C++ programming book for more, and the C++11 standard n3337.
See also this C++ reference website.
If you compile with a recent GCC, enable all warnings and debug info, so use g++ -Wall -Wextra -g then GDB and perhaps valgrind and the address sanitizer or the Clang static analyzer.
Look for inspiration into the source code of existing open source projects on github or gitlab (e.g. FLTK, Qt, fish, Boost, etc... and those mentioned above)
Perhaps consider passing (as a second or more arguments to your getvalue) one or several lambda expression (so practically some std::function) processing the results of different type. Think in terms of callbacks and contination passing style using more a functional programming paradigm.
You are not allowed to return different data types from a single function. However, you can achieve something similar using polymorphism. If all your return types are derived from a single base class, you can make your function return a pointer to that base class, which in turn may point to any one of the derived classes. For example:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
class Datatype
{
public:
virtual string gettype() = 0;
virtual void performOp() = 0;
virtual stringstream& concat(stringstream&) = 0;
virtual ~Datatype() {};
};
class UnsignedInt : public Datatype
{
unsigned int val;
string type { "unsigned int" };
public:
UnsignedInt(unsigned int v): val(v) {}
string gettype() {return type;}
void performOp() { /*perfrom uint specific operations here eg. val = func1(val); */}
stringstream& concat(stringstream& out) {out<<val; return out;}
unsigned int getval() {return val;}
~UnsignedInt() {}
};
class UnsignedLong : public Datatype
{
unsigned long val;
string type { "unsigned long" };
public:
UnsignedLong(unsigned long v): val(v) {}
string gettype() {return type;}
void performOp() { /*perfrom ulong specific operations here eg. val = func2(val); */}
stringstream& concat(stringstream& out) {out<<val; return out;}
unsigned long getval() {return val;}
~UnsignedLong() {}
};
Datatype* getvalue(vector<unsigned char> buffer)
{
if(buffer.size() == 2)
{
// some logic
return new UnsignedInt(23);
}
else if(buffer.size() == 4)
{
//some logic
return new UnsignedLong(2564);
}
else
return nullptr;
}
int main()
{
vector<unsigned char> vec{'2' , '3'};
stringstream out;
Datatype *val = getvalue(vec);
val->performOp(); // perfroms uint specific operation
val->concat(out);
out<<',';
vector<unsigned char> vec1{'2' , '5' , '6' , '4'};
val = getvalue(vec1);
val->performOp(); // perfroms ulong specific operation
val->concat(out);
cout<<out.str()<<endl;
delete val;
return 0;
}

class modify via set/get methods

trying to modify object in the class via get/set methods. I can't understand how change value just only use get/set method.
expected output : "Output : 89".
actual output : "Output : 0"
#include<iostream>
using namespace std;
class TestClass{
public:
int getValue() const{
return _value;
}
void setValue(int value) {
_value = value;
}
private:
int _value;
};
class A{
public:
TestClass getTestClass() const{
return _testClass;
}
void setTestClass(TestClass testClass) {
_testClass = testClass;
}
private:
TestClass _testClass;
};
int main()
{
A a;
a.getTestClass().setValue(89);
cout<<"Output :"<<a.getTestClass().getValue();
}
replace
TestClass getTestClass() const{
return _testClass;
}
with
TestClass& getTestClass() {
return _testClass;
}
You want to return a reference otherwise you are just returning a copy of the variable. But Keep in mind that returning a (non-const) reference to the member variables of a class is not a good design approach.
Some things:
please don't use using namespace std; - read here why.
please don't name your variables _testClass - go with m_testClass instead. You can read hear about the reasoning.
You're returning a copy of _testClass. So when you modify it with setValue(89), nothing happens because you're only modifying a copy that is discarded at the end of the line. Instead, you should return a reference.
Change this here:
TestClass getTestClass() const{
To this:
TestClass &getTestClass() {
And you get the expected output.

Vector of object pointers and virtual methods

First of all sorry if i've chosen wrong title, but wasn't sure how to name it.
Code structure first:
//== 1st file ==
class A {
private:
int x;
public:
int GetX() { return x; }
};
//== 2nd file ==
class B {
private:
A ob1;
public:
virtual A & GetARef() { return ob1; }
};
class C : public B {
private:
A ob2;
public:
A & GetARef() { return ob2; }
};
class D : public B {
public:
// something else w/e
};
//== 3rd file ==
class E {
private:
std::map <int,C> m;
public:
C* GetCPtr(int idx) { return &m[idx]; }
};
//== 4th file ==
void foo(E & E_Obj) {
std::vector <B*> v;
v.push_back(E_Obj.GetCPtr(0));
v.push_back(/*some pointer to D class*/);
Boo(v); // FORGOT TO ADD IT ! Sorry
};
//== 5th file ==
void Boo(std::vector <B*> & v) {
std::cout << v[0]->GetARef().GetX(); // returns B::ob1 's x instead of C::ob2 's x.
};
As wrote in comments, Boo gets wrong 'x'. I just wonder if it's because that pointers go 'out of scope' or I misdesigned something wrong. How to fix that, so I can get proper x (C::ob2 's one).
Sorry for kinda strange class names etc., but orginal code is much longer, so I tried to show the situation only.
#edit
Forgot to add that in Foo() it returns what i expect - C::ob2 's x.
This is the essence of what you are doing
#include <iostream>
using namespace std;
class Base{
const int b = 0;
public:
virtual const int& getInt(){
return b;
}
};
class LeafOverriding : public Base{
const int l = 1;
public:
virtual const int& getInt(){
return l;
}
};
class Leaf : public Base{
};
int main(){
cout << Leaf().getInt() << '\t' << LeafOverriding().getInt() << endl;
}
and it has no problems (i.e. it does indeed output 0 1). I would say that your snippet -- which does not compile, btw -- does not represent the real code.
I'm so lazy I forced you to compile it with C++11 support, because of const int b = 0 and const int l = 1 :)
Sorry for not leaving reply in comments, but I decided it's worth whole post. Also sorry for such late reply. I've spent whole day and night digging slowly through code, since you've proved that my coding was fine (except few typos in example code, sorry for that). Practically after rewriting code letter after letter I finally found the troublemaker somewhere I would normally never look for. My co-worker while sorting some things was switching not the pointers in related vector but their content.
Something like that
vector <E*> v;
// ...
*v[i] = ...
instead of
v[i] = ...
After fixing that, it indeed works as intented. Thanks for your help and clearing things out. Also sorry for wasting your time.

Virtual function implementation C++ not working

I'm new to C++, and I'm trying to write a simple code to compare two objects of subclasses of a parent class called Comparable. I want each subclass to have its own implementation of a method to compare objects based on the data they hold, so I used the virtual keyword:
class Comparable {
public:
virtual int compare(Comparable *other);
};
For example, my subclass HighScoreElement would have its own implementation of compare that would compare the score of the object to the score of another HighScoreElement.
Here is my subclass HighScoreElement:
class HighScoreElement: public Comparable {
public:
virtual int compare(Comparable *other);
HighScoreElement(string user_name, int user_score); // A constructor
private:
int score;
string name;
};
But in my compare implementation in HighScoreElement, I first try to check if the current object's data is the same as other's data. But since the pointer to other is of class Comparable and not HighScoreElement, I can't reference other->score at all in my code, even though HighScoreElement is a subclass of Comparable.
Here is the full code so far:
#include <iostream>
using namespace std;
class Comparable {
public:
virtual int compare(Comparable *other);
};
class HighScoreElement: public Comparable {
public:
virtual int compare(Comparable *other);
HighScoreElement(int user_score, string user_name);
private:
string name;
int score;
};
HighScoreElement::HighScoreElement(int user_score, string user_name) {
name = user_name;
score = user_score;
}
int HighScoreElement::compare(Comparable *other) {
if (this->score == other->score) { // Compiler error right here, other->score is invalid.
// Code to do the comparing if two scores are equal...
}
}
I get a compiler error immediately when I write this code:
if (this->score == other->score)
because other doesn't have data called score, but its subclass, HighScoreElement, does. How can I fix my function implementation so that I can reference the data of "other?" I know my question may sound vague, but any help would be appreciated!
You could implement a virtual function GetScore(), possibly pure virtual in the base class, and use that instead of accessing the field score in your compare function. Make it a const method. On the other hand, Compare could be a method implemented in the base class, that uses this->GetScore() and other->GetScore()
Code stub:
class A {
virtual int getScore() const = 0;
inline bool compare(const A* in) {return (in && this->getScore() == in->getScore());}
//return false also if "in" is set to NULL
}
class B : public A {
int score;
inline int getScore() const {return score;}
}
You can cast the pointer passed to HighScoreElement::compare using "dynamic_cast" (it throws a bad_cast exception on failure).
int HighScoreElement::compare(Comparable *other) {
HighScoreElement *h = NULL;
try
{
ptr = dynamic_cast<HighScoreElement *>(other);
}
catch(std::bad_cast const &)
{
// Handle the bad cast...
}
if (this->score == ptr->score) {
// Code to do the comparing if two scores are equal...
}
}
If you are prepared to accept null pointers, you can use dynamic casts. You can have an overload for the case when you are comparing a HighScoreElement pointer to avoid an unnecessary cast.
#include <iostream>
using namespace std;
class Comparable {
public:
virtual int compare(Comparable *other) = 0; // made pure virtual to compile without definition
};
class HighScoreElement: public Comparable {
public:
virtual int compare(Comparable *other);
int compare(HighScoreElement *other); // comparing to a HighScoreElement ptr, no need to dynamic cast
HighScoreElement(int user_score, string user_name);
private:
string name;
int score;
};
HighScoreElement::HighScoreElement(int user_score, string user_name) {
name = user_name;
score = user_score;
}
int HighScoreElement::compare(Comparable *other) {
HighScoreElement * pHSE = dynamic_cast<HighScoreElement*>(other);
if (pHSE) {
return compare(pHSE);
} else {
return -1; // or however you want to handle compare to non HighScoreElement
}
}
int HighScoreElement::compare(HighScoreElement *other) {
if (this->score == other->score) {
;
}
}
Are you sure it's not
compare( Comparable other )
If (this->score == other.score)

How to return a class object by reference in C++?

I have a class called Object which stores some data.
I would like to return it by reference using a function like this:
Object& return_Object();
Then, in my code, I would call it like this:
Object myObject = return_Object();
I have written code like this and it compiles. However, when I run the code, I consistently get a seg fault. What is the proper way to return a class object by reference?
You're probably returning an object that's on the stack. That is, return_Object() probably looks like this:
Object& return_Object()
{
Object object_to_return;
// ... do stuff ...
return object_to_return;
}
If this is what you're doing, you're out of luck - object_to_return has gone out of scope and been destructed at the end of return_Object, so myObject refers to a non-existent object. You either need to return by value, or return an Object declared in a wider scope or newed onto the heap.
You can only use
Object& return_Object();
if the object returned has a greater scope than the function. For example, you can use it if you have a class where it is encapsulated. If you create an object in your function, use pointers. If you want to modify an existing object, pass it as an argument.
class MyClass{
private:
Object myObj;
public:
Object& return_Object() {
return myObj;
}
Object* return_created_Object() {
return new Object();
}
bool modify_Object( Object& obj) {
// obj = myObj; return true; both possible
return obj.modifySomething() == true;
}
};
You can only return non-local objects by reference. The destructor may have invalidated some internal pointer, or whatever.
Don't be afraid of returning values -- it's fast!
I will show you some examples:
First example, do not return local scope object, for example:
const string &dontDoThis(const string &s)
{
string local = s;
return local;
}
You can't return local by reference, because local is destroyed at the end of the body of dontDoThis.
Second example, you can return by reference:
const string &shorterString(const string &s1, const string &s2)
{
return (s1.size() < s2.size()) ? s1 : s2;
}
Here, you can return by reference both s1 and s2 because they were defined before shorterString was called.
Third example:
char &get_val(string &str, string::size_type ix)
{
return str[ix];
}
usage code as below:
string s("123456");
cout << s << endl;
char &ch = get_val(s, 0);
ch = 'A';
cout << s << endl; // A23456
get_val can return elements of s by reference because s still exists after the call.
Fourth example
class Student
{
public:
string m_name;
int age;
string &getName();
};
string &Student::getName()
{
// you can return by reference
return m_name;
}
string& Test(Student &student)
{
// we can return `m_name` by reference here because `student` still exists after the call
return stu.m_name;
}
usage example:
Student student;
student.m_name = 'jack';
string name = student.getName();
// or
string name2 = Test(student);
Fifth example:
class String
{
private:
char *str_;
public:
String &operator=(const String &str);
};
String &String::operator=(const String &str)
{
if (this == &str)
{
return *this;
}
delete [] str_;
int length = strlen(str.str_);
str_ = new char[length + 1];
strcpy(str_, str.str_);
return *this;
}
You could then use the operator= above like this:
String a;
String b;
String c = b = a;
Well, it is maybe not a really beautiful solution in the code, but it is really beautiful in the interface of your function. And it is also very efficient. It is ideal if the second is more important for you (for example, you are developing a library).
The trick is this:
A line A a = b.make(); is internally converted to a constructor of A, i.e. as if you had written A a(b.make());.
Now b.make() should result a new class, with a callback function.
This whole thing can be fine handled only by classes, without any template.
Here is my minimal example. Check only the main(), as you can see it is simple. The internals aren't.
From the viewpoint of the speed: the size of a Factory::Mediator class is only 2 pointers, which is more that 1 but not more. And this is the only object in the whole thing which is transferred by value.
#include <stdio.h>
class Factory {
public:
class Mediator;
class Result {
public:
Result() {
printf ("Factory::Result::Result()\n");
};
Result(Mediator fm) {
printf ("Factory::Result::Result(Mediator)\n");
fm.call(this);
};
};
typedef void (*MakeMethod)(Factory* factory, Result* result);
class Mediator {
private:
Factory* factory;
MakeMethod makeMethod;
public:
Mediator(Factory* factory, MakeMethod makeMethod) {
printf ("Factory::Mediator::Mediator(Factory*, MakeMethod)\n");
this->factory = factory;
this->makeMethod = makeMethod;
};
void call(Result* result) {
printf ("Factory::Mediator::call(Result*)\n");
(*makeMethod)(factory, result);
};
};
};
class A;
class B : private Factory {
private:
int v;
public:
B(int v) {
printf ("B::B()\n");
this->v = v;
};
int getV() const {
printf ("B::getV()\n");
return v;
};
static void makeCb(Factory* f, Factory::Result* a);
Factory::Mediator make() {
printf ("Factory::Mediator B::make()\n");
return Factory::Mediator(static_cast<Factory*>(this), &B::makeCb);
};
};
class A : private Factory::Result {
friend class B;
private:
int v;
public:
A() {
printf ("A::A()\n");
v = 0;
};
A(Factory::Mediator fm) : Factory::Result(fm) {
printf ("A::A(Factory::Mediator)\n");
};
int getV() const {
printf ("A::getV()\n");
return v;
};
void setV(int v) {
printf ("A::setV(%i)\n", v);
this->v = v;
};
};
void B::makeCb(Factory* f, Factory::Result* r) {
printf ("B::makeCb(Factory*, Factory::Result*)\n");
B* b = static_cast<B*>(f);
A* a = static_cast<A*>(r);
a->setV(b->getV()+1);
};
int main(int argc, char **argv) {
B b(42);
A a = b.make();
printf ("a.v = %i\n", a.getV());
return 0;
}
It isn't really good practice to return an initiated object as it does go out of scope. There are rare instances that this is the desired option. It actually can be done if the class is a referencing counting smart pointer or some other smart pointer.
How does a reference-counting smart pointer's reference counting work?