I'm working on a small game in my free time and while coding it I came across an issue.
I've isolated the issue and made it as small as possible here:
#include <iostream>
#include <memory>
#include <vector>
#include <Windows.h>
class Base
{
public:
std::string p;
virtual ~Base()
{
}
virtual std::vector<std::shared_ptr<std::string>> getText() = 0;
};
class Derived1 : public Base
{
public:
Derived1()
{
p = "from1";
}
std::vector<std::shared_ptr<std::string>> getText()
{
return std::vector<std::shared_ptr<std::string>>{std::shared_ptr<std::string>(&p)};
}
};
class Derived2 : public Base
{
public:
Derived2()
{
p = "from2";
}
std::vector<std::shared_ptr<std::string>> getText()
{
return std::vector<std::shared_ptr<std::string>>{std::shared_ptr<std::string>(&p)};
}
};
int main()
{
std::unique_ptr<Base> state;
std::vector<std::shared_ptr<std::string>> displayText;
state.reset(new Derived1());
displayText = state->getText();
while(1)
{
for(auto i = displayText.begin(); i != displayText.end(); ++i)
std::cout << **i;
if (GetKeyState('2') < 0)
{
state.reset(new Derived2());
displayText.clear();
displayText = state->getText();
}
else if (GetKeyState('1') < 0)
{
state.reset(new Derived1());
displayText.clear();
displayText = state->getText();
}
}
return 0;
}
When pressing "1" and "2" back and forth it seems to work sometimes, and when I exit out I get something like -1073741510 or similar as the return value. In my game code it also seems to crash a lot.
(By exit out I mean using the X button on the command window, sorry for not clarifying)
After doing some research on unique_ptr and pointers in general along with polymorphic classes I still can't understand why this behaves the way it does.
So, what's going on here?
You are creating a shared_ptr from a stack variable. This will end up calling delete on p which is not safe. See Calling delete on variable allocated on the stack
EDIT:
You would need to make p a pointer. You could do something like the following:
class Base
{
public:
std::shared_ptr<std::string> p;
virtual ~Base()
{
}
virtual std::vector<std::shared_ptr<std::string>> getText() = 0;
};
class Derived1 : public Base
{
public:
Derived1()
{
p = std::make_shared<std::string>("from1");
}
std::vector<std::shared_ptr<std::string>> getText()
{
return std::vector<std::shared_ptr<std::string>>{p};
}
};
class Derived2 : public Base
{
public:
Derived2()
{
p = std::make_shared<std::string>("from2");
}
std::vector<std::shared_ptr<std::string>> getText()
{
return std::vector<std::shared_ptr<std::string>>{p};
}
};
Related
What is the easiest way to create an object on stack based on a certain condition within the current scope?
Assume my current code is:
Base obj();
obj.print();
Now I want to change the code to 'plugin' a different derived class e.g. :
bool doBase=true;
doBase ? Base obj() : Derived obj();
obj.print();
But this of course does not work?
I know how to get this working, e.g. with an if, however my print in this example is in real world say 10-50 lines so this result in code duplication. Another approach is dynamically creating the objects, but I am curious there is a way to fix this without dynamically creating the objects.
bool doBase=true;
if (doBase) {
Base obj();
obj.print();
} else {
Derived obj();
obj.print(); // CODE DUPLICATION
}
Full snippet:
#include <iostream>
class Base {
virtual void print() { std::cout << "In base"<<std::endl; }
};
class Derived : public Base {
virtual void print() override { std::cout << "In derived"<<std::endl; }
};
int main() {
bool doBase=true;
doBase ? Base obj() : Derived obj();
obj.print();
doBase=false;
doBase ? Base obj2() : Derived obj2();
obj2.print();
}
You could use lambdas to wrap the repetitive code, eg:
#include <iostream>
class Base {
public:
virtual void print() { std::cout << "In base"<<std::endl; }
};
class Derived : public Base {
public:
virtual void print() override { std::cout << "In derived"<<std::endl; }
};
int main() {
auto print = [](Base &&obj){ obj.print(); };
auto doIt = [&print](bool doBase) { doBase ? print(Base{}) : print(Derived{}); };
doIt(true);
doIt(false);
}
Online Demo
Alternatively, use std::variant, eg:
#include <iostream>
#include <variant>
class Base {
public:
virtual void print() { std::cout << "In base"<<std::endl; }
};
class Derived : public Base {
public:
virtual void print() override { std::cout << "In derived"<<std::endl; }
};
int main() {
auto print = [](Base& obj){ obj.print(); };
auto doIt = [&print](bool doBase) {
std::variant<Base, Derived> v;
if (doBase) {
v = Base{};
} else {
v = Derived{};
}
std::visit(print, v);
};
doIt(true);
doIt(false);
return 0;
}
Online Demo
I have a code which has many derived class from a single base class. I wrote this code when there is minimum required and currently the specification changes so I need to create some 100+ derived classes.
My earlier implementation was something like
class Base {
public:
Base();
virtual ~Base();
virtual bool isThereError() { return false;}
virtual int configureMe() { return 0; }
virtual int executeMe() { return 0;}
};
class Derived_1 : public Base {
public:
Derived_1() {
errorStatus = false;
//Some initialization code for this class }
virtual ~Derived_1() {}
bool isThereError() { return errorStatus;}
int configureMe() {
// configuration code for this class
return 0;
}
int executeMe() {
//execute the major functionality of this class based on the configuration
return 0;
}
private:
bool errorStatus;
};
class Derived_2 : public Base {
public:
Derived_2() {
errorStatus = false;
//Some initialization code for this class }
virtual ~Derived_2() {}
bool isThereError() { return errorStatus;}
int configureMe() {
// configuration code for this class
return 0;
}
int executeMe() {
//execute the major functionality of this class based on the configuration
return 0;
}
private:
bool errorStatus;
};
Main.cpp:
#include "Base.h"
#include "Derived_1.h"
#include "Derived_2.h"
#include <set>
Derived_1 *dv1Ptr;
Derived_2 *dv2Ptr;
typedef std::set<Base *> ClassPtrList;
int main() {
ClassPtrList cpList;
dv1Ptr = new Derived_1();
dv2Ptr = new Derived_2();
dv1Ptr->configureMe();
if(dv1Ptr->isThereError()){
cpList.insert(dv1Ptr);
}
dv2Ptr->configureMe();
if(dv2Ptr->isThereError()){
cpList.insert(dv2Ptr);
}
while(true) {
for(ClassPtrList::iterator iter = cpList.begin(); iter != cpList.end(); ++iter) {
(*iter)->executeMe();
}
Sleep(1000);
}
}
I found the above implementation would lengthen the number of line and it is also not a good practice to write such a form of code when there are more derived classes. I need to write a code using MACRO or any other type, so that each derive class get instantiated by itself and the ClassPtrList keeps the pointer of all the derived class.
I started with something like,
#define CTOR_DERIVED(drvClass) return new drvClass()
but I'm not sure how to avoid creating pointer to update the list. I need to create 287 such derived classes.
Thanks in advance.
I'm pretty new to object oriented programming in C++, and I can't find a solution to the following problem, I hope this is even possible.
I've got 3 classes: Base and Child, Child2.
All of them got the function talk();.
I want to store Base, Child and Child2 objects in an array, and iterate through them and execute their talk() functions.
This is what I want them to print:
- Base: "base"
- Child: "child"
- Child2: "child2"
Here are my classes:
class Base {
public:
virtual void talk() {
printf("base\n");
}
}
class Child : public Base {
public:
using Base:draw;
void talk() {
printf("child\n");
}
}
class Child2 : public Base {
public:
using Base:draw;
void talk() {
printf("child2\n");
}
}
here is my array:
Base objects[3];
objects[0] = Base();
objects[1] = Child();
objects[2] = Child2();
for(int i = 0; i < 3; i++) {
objects[i]->talk();
}
And the output should be:
base
child
child2
Your code is slicing the objects. When you assign a variable of the base class to the value of derived class, you end up with a base object. At this point, nothing is left of the original derived class, all you have is a base class.
In C++ the way to treat objects polymorphically - that is, to retain the information of original type - is to use either a reference or a pointer. However, you can not put references into arrays.
Which means, you need an array of pointers - but not raw pointers. You want so-called smart pointers. Putting it all together, this is how your code should look like:
std::unique_ptr<Base> objects[3] = {new Base(), new Child(), new Child2()};
for(int i = 0; i < 3; i++) {
objects[i]->talk();
}
Perhaps something like this?
#include <iostream>
#include <cstdio>
class Base
{
public:
virtual void talk()
{
printf("base\n");
}
};
class Child : public Base
{
public:
void talk()
{
printf("child\n");
}
};
class Child2 : public Base
{
public:
void talk()
{
printf("child2\n");
}
};
int main()
{
Base** objects;
objects = new Base * [3];
objects[0] = new Base();
objects[1] = new Child();
objects[2] = new Child2();
for(int i = 0; i < 3; i++)
objects[i]->talk();
}
Output is:
base
child
child2
So something like:
#include <stdio.h>
class Base {
public:
virtual void talk() {
printf("base\n");
}
};
class Child : public Base {
public:
void talk()
{
printf("child\n");
}
};
class Child2 : public Base {
public:
void talk()
{
printf("child2\n");
}
};
int main()
{
Base* objects[3];
objects[0] = new Base();
objects[1] = new Child();
objects[2] = new Child2();
for(int i = 0; i < 3; i++) {
objects[i]->talk();
}
}
I have some code like:
class Base {
virtual bool acceptsData(char*) = 0;
};
class Derived1 : public Base {
virtual bool acceptsData(char*) { /* do something */ }
};
class Derived2 : public Base {
virtual bool acceptsData(char*) { /* do something else */}
}
Base* createStuff(char* data)
{
Base* d1 = new Derived1();
if(d1->acceptsData(data))
{
return d1;
}
delete d1;
Base* d2 = new Derived2();
if(d2->acceptsData(data))
{
return d2;
}
delete d2;
// and more ...
}
// .... somewhere later
int main()
{
Base* Aclass = createStuff("abc");
}
I'd like to get rid of this long if() ... construct, and use some more generalized patterns, but I still did not manager to come up with something useful. Is there a better way of doing this?
If you want to factorize code as you have several Derived classes, you may use something like the following:
namespace detail
{
template <typename T> std::unique_ptr<Base> make_base(const char* data)
{
std::unique_ptr<Base> base = std::make_unique<T>();
if (base->acceptsData(data)) {
return base;
}
return nullptr;
}
template <typename... Ts> std::unique_ptr<Base> createStuff(const char* data)
{
std::function<std::unique_ptr<Base>(const char*)> fs[] = { make_base<Ts>... };
for(auto& f : fs) {
auto base = f(data);
if(base) {
return base;
}
}
return nullptr;
}
}
Base* createStuff(const char* data) {
return detail::createStuff<Derived1, Derived2/* and other Derived classes*/>(data).release();
}
Live example.
You are creating your objects. Factory or Builder are suitable patterns for you.
What might meet your requirements is something the virtual constructors design pattern. This is what it looks like...
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Base {
Base* b;
// suppress the usual constructors
Base(Base&);
Base operator=(Base&);
protected:
Base() { b = 0; };
public:
virtual void Print() { b->Print(); }
virtual ~Base() {
if (b) {
delete b;
}
}
Base(string type);
};
class Derived1 : public Base {
Derived1(Derived1&);
Derived1 operator=(Derived1&);
Derived1() {}
friend class Base;
public:
void Print() { cout << "Derived1::Print()" << endl; }
~Derived1() { }
};
class Derived2 : public Base {
Derived2(Derived2&);
Derived2 operator=(Derived2&);
Derived2() {}
friend class Base;
public:
void Print() { cout << "Derived2::Print()" << endl; }
~Derived2() { }
};
Base::Base(string type) {
if (type == "Derived1")
b = new Derived1;
else if (type == "Derived2")
b = new Derived2;
}
int main() {
vector<Base*> bases;
cout << "virtual constructor calls:" << endl;
bases.push_back(new Base("Derived2"));
bases.push_back(new Base("Derived1"));
bases.push_back(new Base("Derived1"));
bases.push_back(new Base("Derived2"));
for (int i = 0; i < bases.size(); i++) {
bases[i]->Print();
}
cout << "destructor calls:" << endl;
for (int j = 0; j < bases.size(); j++) {
delete bases[j];
}
// system("pause");
return 0;
}
I have a hierarchie of classes that implement the Prototype pattern and I would like to use move semantics to limit objects deep copy. I tried to adapted the pattern with a move() member function which meaning is that I do not need the original object anymore. Here is what I have so far:
#include <iostream>
#include <utility>
#include <vector>
struct base
{
virtual ~base() { }
virtual base* clone() const = 0;
virtual base* move() = 0;
};
struct derived1 : public base
{
derived1() { std::cout << "derived1::derived1()\n"; }
derived1(const derived1&) { std::cout << "derived1::derived1(const derived1&)\n"; }
derived1(derived1&&) { std::cout << "derived1::derived1(derived1&&)\n"; }
virtual ~derived1() { }
virtual base* clone() const { return new derived1(*this); }
virtual base* move() { return new derived1(std::move(*this)); }
};
struct derived2 : public base
{
derived2() { std::cout << "derived2::derived2()\n"; }
derived2(const derived2&) { std::cout << "derived2::derived2(const derived2&)\n"; }
derived2(derived2&&) { std::cout << "derived2::derived2(derived2&&)\n"; }
virtual ~derived2() { }
virtual base* clone() const { return new derived2(*this); }
virtual base* move() { return new derived2(std::move(*this)); }
};
std::vector<base*> vec;
void foo(const base& obj)
{
vec.push_back(obj.clone());
}
void foo(base&& obj)
{
vec.push_back(obj.move());
}
int main()
{
derived1 d1;
derived2 d2;
foo(d1);
foo(d2);
foo(derived1());
foo(derived2());
}
When I run it, it show that the good constructors are used:
derived1::derived1()
derived2::derived2()
derived1::derived1(const derived1&)
derived2::derived2(const derived2&)
derived1::derived1()
derived1::derived1(derived1&&)
derived2::derived2()
derived2::derived2(derived2&&)
So far, it seems good. I am just not sure if this is a standard compliant usage of the rvalue references. Is there a point I did not think of that would produce undesirable results?
For recurring method definition I prefer CRTP. For your case I'd declare something like:
template<typename TDerived>
class virtually_clonable : public base
{
public:
virtual base* clone() override
{
return new TDerived(*AsDerived());
}
virtual base* move() override
{
return new TDerived(std::move(*AsDerived()));
}
private:
TDerived* AsDerived()
{
return static_cast<TDerived*>(this);
}
};
And while implementing the classes:
class derived1 : public virtually_clonable<derived1>
{
public:
/* your ctors goes here*/
/* no need to implement clone/move again */
};
class derived2 : public virtually_clonable<derived2>
{
public:
/* your ctors goes here*/
/* no need to implement clone/move again */
};
By the way you may want to return shared_ptr objects instead of raw pointers. That is usually the case for clonable types instead of unique_ptr.