check object existance when function retuning pass by reference - c++

I have very basic issue and have following code. In rare cases, we are not able to call setDriver(set driver object) and call getDriver function for calling driver class function which resultant memory crash( as setdriver has not set). is it possible to check getdriver object. I have tried to set NULL but as we are returning reference it's not appropriate/feasible.
include<iostream>
#include<string>
using namespace std;
class Driver {
private:
string name;
public:
void setname(string name);
void display();
};
void Driver::setname(string name)
{
this->name = name;
}
void Driver::display()
{
cout<<" This driver is .."<<name<<endl;
}
class sample {
protected:
Driver *m_d;
public:
void setDriver(Driver *driver);
Driver& getDriver();
};
void sample::setDriver(Driver *driver)
{
m_d = driver;
}
Driver& sample::getDriver()
{
return *m_d;
}
int main()
{
sample s;
Driver *d = new Driver;
d->setname("test");
s.setDriver(d);
Driver &d1 = s.getDriver();
// How can I check if d1 is exist or not
d1.display();
}
After getting input from below discussion, I have modified code into following way. will it be correct solution?
#include<iostream>
#include<string>
using namespace std;
class Driver {
private:
string name;
public:
void setname(string name);
void display();
};
void Driver::setname(string name)
{
this->name = name;
}
void Driver::display()
{
cout<<" This driver is .."<<name<<endl;
}
class sample {
protected:
Driver *m_d;
public:
void setDriver(Driver *driver);
Driver& getDriver();
sample();
};
sample::sample()
{
m_d = NULL;
}
void sample::setDriver(Driver *driver)
{
m_d = driver;
}
Driver& sample::getDriver()
{
if(m_d)
return *m_d;
else
throw "Error";
}
int main()
{
sample s;
Driver *d = new Driver;
d->setname("test");
s.setDriver(d);
try{
Driver &d1 = s.getDriver();
d1.display();
}
catch(...)
{
cout<<" object is not prsent"<<endl;
}

References can't point to nothing so I suggest two options:
a) throw an exception - this for me is clearly the best solution; this is an edge case and very appropriate for exception handling
b) Include a method driver.isLoaded() which the caller can check - in the case when you can't allocate a driver return a stub driver which returns this value as false
Alternately you need to change the nature of the call to return a pointer (so that you can return null) or pass your driver as a reference parameter and return a boolean to indicate success. Neither of these options seems as good as a above to me.

A safe way to don't have to check if pointer is null is to force it to never be:
class sample {
public:
// No default constructor
explicit sample(Driver &driver) m_d(&driver) {}
void setDriver(Driver &driver) { m_d = &driver; }
Driver& getDriver() { return *m_d; }
private:
Driver *m_d;
};
Usage:
int main()
{
Driver d1;
d1.setname("test1");
Driver d2;
d2.setName("test2");
sample s(d1);
s.getDriver().display();
s.setDriver(d2);
s.getDriver().display();
}

Related

Convert c++98 code to new c++17 code when using std::vector of pointers

i dont what to manage or less as i can manage raw pointers note in the example i have to delete the object before removeing it from the vector i want to avoid it it here and later
what will be good case to convert this code to using unique_ptr or shared_ptr
class GameState
{
public:
virtual bool onEnter() = 0;
virtual bool onExit() = 0;
virtual std::string getStateID() const = 0;
};
class MenuState : GameState
{
public:
MenuState(){};
virtual ~MenuState(){};
bool onEnter(){};
bool onExit(){};
std::string getStateID() const;
private:
static const std::string s_menuId;
};
class StateMechine
{
public:
void pushState(GameState* pState)
{
m_gameStates.pop_back(pState);
m_gameStates.back()->onEnter();
}
void changeState(GameState* pState)
{
if(!m_gameStates.empty())
{
if(m_gameStates.back()->onExit())
{
delete m_gameStates.back();
m_gameStates.pop_back();
}
}
}
private:
std::vector<GameState*> m_gameStates;
}
int main(int argc ,char** argv)
{
GameState *gs = new MenuState();
StateMechine sm;
sm.pushState(gs);
sm.changeState(gs);
}
The std::vector<GameState*> can be replaced with a std::vector<std::unique_ptr<GameState>>. That way a call to m_gameStates.pop_back() will delete the corresponding object.
class StateMechine
{
public:
void pushState(std::unique_ptr<GameState> pState)
{
m_gameStates.push_back(std::move(pState));
m_gameStates.back()->onEnter();
}
void changeState()
{
if(!m_gameStates.empty())
{
if(m_gameStates.back()->onExit())
{
m_gameStates.pop_back();
}
}
}
private:
std::vector<std::unique_ptr<GameState>> m_gameStates;
};
int main(int argc ,char** argv)
{
StateMechine sm;
sm.pushState(std::make_unique<MenuState>());
sm.changeState();
}

Segmentation fault with shared pointers

What's wrong with this code (I minimized my whole code)? I can't figure out why pu.useIt(); causes a segmentation fault.
#include <memory>
using namespace std;
class Person {
private:
shared_ptr<string> name;
public:
void setName(shared_ptr<string> name) {
this->name = name;
}
shared_ptr<string> getName() {
return name;
}
};
class PersonCreator {
shared_ptr<Person> person;
public:
void createAmy() {
shared_ptr<string> amysName = make_shared<string>("amy");
person->setName(amysName);
}
};
class PersonUser {
public:
void useIt() {
PersonCreator pc;
pc.createAmy();
}
};
int main()
{
PersonUser pu;
pu.useIt();
return 0;
}
You need to initialize person, now it is empty, default ctor of shared_ptr means that it points to nullptr:
void createAmy() {
shared_ptr<string> amysName = make_shared<string>("amy");
person = std::make_shared<Person>(); // added
person->setName(amysName);
}

Issue with polymorphism with smart pointers and vectors c++

I am currently trying to learn c++ and I am having an issue when trying to create a vector which iterates through several different objects whom all inherit from the same base class with smart pointers.
I parse a file and create the objects and insert them into the vector depending on the character parsed but I keep getting the error:
Error C2664 'std::unique_ptr<Test *,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': cannot convert argument 1 from 'std::unique_ptr<Test2,std::default_delete<_Ty>>' to 'std::nullptr_t'"
Code is as follows:
class Test {
public:
virtual ~Test(){}
virtual int update() {}
};
class Test2 : public Test {
private:
int a;
public:
Test2() {
}
Test2(int n) {
a = n;
}
int update() override {
return a;
}
};
class Test3 : public Test {
private:
int a;
public:
Test3() {
}
Test3(int n) {
a = n;
}
int update() override {
return a;
}
};
class Test4 : public Test {
private:
int a;
public:
Test4() {
}
Test4(int n) {
a = n;
}
int update() override {
return a;
}
};
class manager {
private:
std::vector<std::unique_ptr<Test*>> vList;
std::ifstream lvlFile;
public:
std::string tmp;
manager() {
}
~manager() {
}
void init(const char *path) {
lvlFile.open(path, 0);
while (lvlFile.eof() != true) {
std::getline(lvlFile, tmp);
for (char& a : tmp) {
switch (a) {
case 'w':
vList.emplace_back(std::make_unique<Test2>(2));
break;
case 'g':
vList.emplace_back(std::make_unique<Test3>(3));
break;
}
}
}
}
void print() {
for (auto& i : vList) {
std::cout << (*i)->update() << std::endl;
}
}
};
manager *m;
int main() {
m = new manager();
m->init("lvl.txt");
_getch();
}
Maybe I have misunderstood something crucial here but I have been looking around and found no real answers so any pointers to this would be most welcome!
Change std::vector<std::unique_ptr<Test*>> to std::vector<std::unique_ptr<Test>>.
std::unique_ptr<Test*> is a pointer to pointer (Test**).

Can I override a string return type functions in c++

I cannot understand why this does not compile:
#include<iostream>
#include<string>
using namespace std;
class Product {
public:
virtual void print() = 0;
virtual void slog() = 0;
virtual void loft() = 0;
};
class Bike: public Product {
private:
string s;
public:
Bike(string x){
s = x;
}
void print() {
std::cout << "Bike";
}
int slog() {
return 4;
}
string loft() {
return s;
}
};
int main() {
string s("Hello");
Product *p = new Bike(s);
p->print(); //works fine
cout << p->slog();//works fine
cout << p->loft(); //error
return 0;
}
The above code results in error. Why can't I override string class.
I want to call loft() using the pointer p.
Is there any way to achieve this using pointer object to abstract class Product
Firstly, you need to include string #include <string>.
There's no problem with loft method, you have a problem with print method. Child class has a return type of string and base class has a return type of void, thus you're not really overriding the function. Compiler sees the declaration of void print() in base class and you can't do a cout on that.
Here's your code with few fixes and comments on them, it should work fine.
#include <iostream>
#include <string>
using namespace std;
class Product {
public:
virtual void print() = 0;
virtual int slog() = 0;
virtual string loft() = 0;
//added virtual destructor so you can use pointer to base class for child classes correctly
virtual ~Product() {};
};
class Bike: public Product {
string s;
public:
Bike(string x) {
s = x;
}
void print() {
cout << "Bike";
}
int slog() {
return 4;
}
string loft() {
return s;
}
};
int main() {
string s("Hello");
Product *p = new Bike(s);
p->print();
cout << p->slog();
cout << p->loft();
return 0;
}
Also, please try to format your code better next time, it makes it easier to read

Stop Code instead of break with a Error Message

Here is some code that is from a great website which does what i want quite well (searching in a vector of class objects by addressing the class objects).
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
using namespacestd;
class class1
{
private:
int id;
double value;
public:
class1(int i, double v) :id(i), value(v){ }
int getId()const { return id; }
double getValue() const { return value; }
};
class HasIdentifier :public unary_function<class1, bool>
{
public:
HasIdentifier(int id) : m_id(id) { }
bool operator()(const class1& c)const
{
return (c.getId() == m_id);
}
private:
int m_id;
};
class class2
{
private:
vector <class1> objects;
public:
class2()
{
objects.push_back(class1(1, 100.0));
objects.push_back(class1(2, 100.0));
objects.push_back(class1(3, 100.0));
}
double GetValueOfId(int id)
{
vector<class1>::iterator itElem = find_if(objects.begin(), objects.end(), HasIdentifier(id));
return itElem->getValue();
}
};
int main() {
class2 c;
int id = 4;
cout << id << " " << c.GetValueOfId(id);
cin.get();
return 0;
}
It works well but whenenver i put "int id ">3 it crashes because object only has the size 3. I got this, but is there a possibility to get warned when this will happen so that is does not crash but im able to correct it somehow in the code with a warn message?
You should check the returned iterator for validness and throw and exception (or report an error any other way) if it is invalid:
if (itElem == objects.end())
throw MyVeryCoolException("Woops wrong id");
Dont forget to set up a global exception handler (toplevel catch), otherwise your application will still crash if the exception is uncaught.