I have a Singleton class that manages a container of Items, exposing public functions that allow Items to be added or removed from the container.
class Item;
typedef std::shared_ptr<Item> ItemPtr;
class Singleton
{
public:
static Singleton& Instance()
{
static std::unique_ptr<Singleton> Instance(new Singleton);
return *Instance;
}
void Add(ItemPtr item)
{
mContainer.push_back(item);
}
void Remove(ItemPtr item)
{
for (auto it = mContainer.begin(); it != mContainer.end(); it++)
if (*it == item)
mContainer.erase(it);
}
private:
std::vector<ItemPtr> mContainer;
};
I'd like Item to have the ability to add itself to the Singleton container via an Add() method, and remove itself from the container upon its destruction.
class Item
{
public:
Item() {}
~Item()
{
Singleton::Instance().Remove(ItemPtr(this));
}
void Add()
{
Singleton::Instance().Add(ItemPtr(this));
}
};
When I run the example below, I get a crash on Singleton::Remove(), specifically a EXC_BAD_ACCESS on mContainer.begin().
int main()
{
Item* a = new Item();
Item* b = new Item();
a->Add();
b->Add();
delete a;
delete b;
}
This seems to indicate that mContainer no longer exists. Looking at the call stack, I can also see one of the root call stack frames is the destructor Singleton::~Singleton(), which would explain why mContainer is no longer there.
I've tried a different approach : instead of using std::shared_ptr<Item> I simply used raw pointers (i.e., Item*) with the appropriate substitutions in the code. It worked without problems.
My questions are:
I guess what's happening is that the ownership of the Item objects is only released by the shared_ptr after the destruction of Singleton, which causes the error. Is this correct?
Is it impossible to do what I want to do if the container in Singleton is of shared_ptr<Item>?
If not, how could I do it?
The wisdom of doing this in the first place notwithstanding, what you want can be achieved if you're willing to use, and abide by the restrictions of, std::enabled_shared_from_this. See below:
#include <iostream>
#include <algorithm>
#include <memory>
#include <vector>
struct Item;
typedef std::shared_ptr<Item> ItemPtr;
class Singleton
{
private:
Singleton() {}
public:
static Singleton &Instance()
{
static Singleton s;
return s;
}
void Add(ItemPtr item)
{
mContainer.emplace_back(std::move(item));
}
void Remove(const ItemPtr& item)
{
mContainer.erase(
std::remove(mContainer.begin(), mContainer.end(), item),
mContainer.end());
}
void Clear()
{
mContainer.clear();
}
private:
std::vector<ItemPtr> mContainer;
};
// note derivation. this means you can get a std::shared_ptr<Item>
// via `shared_from_this` , but it also means the object itself
// MUST be an actual shared object to begin with.
struct Item : public std::enable_shared_from_this<Item>
{
void Add()
{
Singleton::Instance().Add(shared_from_this());
}
};
int main()
{
ItemPtr a = std::make_shared<Item>();
ItemPtr b = std::make_shared<Item>();
// add to the singleton container
a->Add();
b->Add();
// report reference count of 'a'
std::cout << "before removal 'a' has " << a.use_count() << " references\n";
Singleton::Instance().Remove(a);
std::cout << "after removal 'a' has " << a.use_count() << " references\n";
}
Output
before removal 'a' has 2 references
after removal 'a' has 1 references
The most important part of this is the creation of a and b in main . Notice they are, in fact, managed by std::shared_ptr enshrouding from inception. This is required for std::enable_shared_from_this to work correctly. The rest is fairly straight forward. The ability to get a reference-bumped std::shared_ptr from within the body of any member of Item is done via the shared_from_this() member provided from the base class std::enable_shared_from_this.
In short, taking this approach will work for you, but at no point can you use shared_from_this() unless the object it is being fired upon is already managed by a std::shared_ptr in the first place. Keep that in mind.
Related
I have multiple child classes inside a parent class vector where each child has it's own type. The parent has a virtual getType function and each child overrides it with it's own; not even sure if I need this TBH but I got from this Access child members within parent class, C++
When I loop over the vector (loop not shown here), the type is only that of the parent, since it's a vector of Parents, but I need the type of each individual child made with it's own constructor.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Parent
{
private:
string type = "parent";
public:
virtual string getType()
{
return type;
}
};
class Child1 : public Parent
{
string type = "type1";
public:
string getType()
{
return type;
}
};
class Child2 : public Parent
{
string type = "type2";
public:
string getType()
{
return type;
}
};
//main.cpp
int main()
{
vector<Parent> children;
Child1 t1;
Child2 t2;
children.push_back(t1);
children.push_back(t2);
//THIS WORKS
cout << t1.getType(); // returns type1
// I NEED THIS TO WORK
cout << children[0].getType(); // returns parent.
cout << children[1].getType(); // I need type1 && type2
}
How can I do this? I have no way of knowing what type of child each is otherwise, or is there another way to do this?
You just experimented slicing.
A Child is a Parent plus a few more things.
When you try to put a Child in the vector of Parent, only the Parent part of each of these Children is put in the vector (because the vector does not contain Children but Parents); hence the name slicing.
In order to obtain the dynamic polymorphism you are looking for, you need a vector of pointers to Parent; this way, each pointed-to element can be whether a Parent or a Child and behave accordingly.
This is often done with a dynamic allocation of each element in the vector, but this is not mandatory. For example, you could store all the Parents in a vector, all the Children 1 in another, and so on, and finally use a vector of pointers to designate some of them in any order.
If you decide to allocate each Parent/Child individually, you should consider smart-pointers like std::unique_ptr<T> rather than raw pointers and new/delete.
You will find below your example slightly modified in order to obtain dynamic polymorphism.
It relies on dynamic allocation of each element thanks to std::unique_ptr<T>/std::make_unique().
Note that, because of dynamic polymorphism, you need a virtual destructor (even if it does nothing special).
Since this hierarchy of types is intended for dynamic polymorphism, it is encouraged to prevent slicing (that you have just experienced) by forbidding the use of copy/move operations.
Thus, you have to provide one or several constructors that fulfil your needs (but this is quite common).
My last advice is « avoid dynamic polymorphism; prefer template » but it is another topic ;^)
/**
g++ -std=c++17 -o prog_cpp prog_cpp.cpp \
-pedantic -Wall -Wextra -Wconversion -Wno-sign-conversion \
-g -O0 -UNDEBUG -fsanitize=address,undefined
**/
#include <iostream>
#include <string>
#include <vector>
#include <memory> // std::unique_ptr<T>, std::make_unique()
class Parent
{
public:
virtual ~Parent() =default; // ensure correct destruction
// forbid copy and move in order to prevent slicing
Parent(const Parent &) =delete;
Parent &operator=(const Parent &) =delete;
Parent(Parent &&) =delete;
Parent &operator=(Parent &&) =delete;
Parent() =default; // provide a suitable constructor
virtual
const std::string &
getType() const
{
return type;
}
private:
// inline static // is probably better
const std::string type{"parent"};
};
class Child1: public Parent
{
public:
const std::string &
getType() const override
{
return type;
}
private:
// inline static // is probably better
const std::string type{"type1"};
};
class Child2 : public Parent
{
public:
const std::string &
getType() const override
{
return type;
}
private:
// inline static // is probably better
const std::string type{"type2"};
};
int
main()
{
const auto p=Parent{};
std::cout << "p: " << p.getType() << '\n';
const auto c1=Child1{};
std::cout << "c1: " << c1.getType() << '\n';
const auto c2=Child2{};
std::cout << "c2: " << c2.getType() << '\n';
auto people=std::vector<std::unique_ptr<Parent>>{};
for(auto i=0; i<2; ++i)
{
people.emplace_back(std::make_unique<Parent>());
people.emplace_back(std::make_unique<Child1>());
people.emplace_back(std::make_unique<Child2>());
}
for(const auto &e: people)
{
std::cout << e->getType() << '\n';
}
return 0;
}
from what I've discerned by reading through most of the questions on here that pop up when looking up unique pointers, this seems to me like it should provide the behavior described by the Builder pattern.
I want any instance of Builder (or its sub-classes, since it doesn't implement any procedures for modifying the object under construction) to own the object under construction until Close returns the unique pointer to the caller, at which point the caller takes ownership.
Builder.h
template <class type> class Builder
{
public:
~Builder();
unique_ptr<type> Close();
protected:
Builder();
unique_ptr<type> _uptr;
};
Builder.cpp
template<class type> Builder<type>::Builder()
{
uptr = make_unique<type>();
}
template<class type> Builder<type>::~Builder()
{}
template<class type> unique_ptr<type> Builder<type>::Close()
{
return uptr;
}
Do I understand the semantics of passing a unique pointer by value?
(includes and namespaces omitted for brevity / legibility)
std::unique_ptr cannot be copied. Instead, you will have to move uptr in order to properly transfer ownership of the underlying pointer.
template<class type> unique_ptr<type> Builder<type>::Close()
{
return std::move(uptr);
}
Do I understand the semantics of passing a unique pointer by value?
You can move from a unique_ptr: std::move(this->_uptr)
Be cautious with moves as they invalidate the contents of the original object.
I've completed your example to exemplify the threat:
#include <iostream>
#include <memory>
template<typename T> class Builder
{
public:
virtual ~Builder() {}
std::unique_ptr<T> Close();
protected:
Builder() {}
std::unique_ptr<T> _uptr;
};
class IntBuilder: public Builder<int>
{
public:
IntBuilder() : Builder<int>() {
this->_uptr = std::unique_ptr<int>(new int);
}
void setValue(int x) {
*(this->_uptr) = x;
}
std::unique_ptr<int> Close() {
return std::move(this->_uptr);
}
};
int main() {
IntBuilder b;
b.setValue(3);
auto i = b.Close();
std::cout << *i << std::endl; // OK
auto i2 = b.Close();
std::cout << *i2 << std::endl; // Segmentation fault
}
Although this->_uptr was moved within IntBuilder::Close(), the compiler will not warn you about the Segfault potential.
Furthermore I'd recommend just using T Builder<T>::Close() instead of unique_ptr<T> Builder<T>::Close() as the latter just limits flexibility of the class.
Also why not have sub-classes manage the instance they're creating. If the instance they're creating cannot be mutated the sub-class needs to store information about the instance until its creation (at Close()) and will unnecessarily carry along the unique_ptr<T>.
Here's how I'd alter the Builder class:
template<typename T> class Builder
{
public:
virtual ~Builder() {}
T&& Close();
protected:
Builder() {}
};
Is there a way through which we can get all the objects of a class in C++.Like in Python we can do
class_name.objects.all()
to get all the objects of a class.What's its analog in C++,if it exists?
You can do this yourself, but make sure you know what you're doing.
How:
There's nothing within C++ that already does this, but it's pretty easy to do this yourself. The key is to recognize that a class can have static member variables and functions (i.e. functions that belong to the whole class, rather than to individual objects of the class).
So you can use some kind of table or other data structure to store a reference to each object. Like so:
class A {
public:
//constructor assigns this object an id based on the static value curID,
//which is common to the class (i.e. the next class to call the constructor
//will be assigned an id thats 1 more than this one
//also, constructor adds the pointer to this object to a static map of ids
//to objects. This way, the map can be queried for the pointer to an object
//that has a particular id
A() {
id = curID++;
objects[id] = this;
}
//copy constructor ensures an object copied from another does not
//take the id of the other object, and gets added to the map
A(const A&) {
id = curID++; //don't want have the same ID as the object we are copying from
objects[id] = this;
x = A.x;
y = A.y;
}
A& operator=(const A&) {
id = curID++;
objects[id] = this;
x = A.x;
y = A.y;
return *this;
}
//destructor removes the pointer to this object from the map
~A() {
objects.erase(id);
}
//function to get the map that stores all the objects
static map<int, A*>& GetMapOfObjects() {
return objects;
}
private:
//the following variable is **static**, which means it does not
//belong to a single object but to the whole class. Here, it is
//used to generate a unique ID for every new object that's
//instantiated. If you have a lot of objects (e.g. more than
//32,767), consider using a long int
static int curID;
//this variable is also static, and is map that stores a pointer
//to each object. This way, you can access the pointer to a
//particular object using its ID. Depending on what you need, you
//could use other structures than a map
static map<int, A*> objects;
//this is a (non-static) member variable, i.e. unique to each object.
//Its value is determined in the constructor, making use of curID.
int id;
//these are some other member variables, depending on what your object actually is
double x;
double y;
}
Note: The above design is very basic and not complete, but just meant to give you an idea of how to implement what you're asking for using static members/functions. For example, for operations that you want to perform on all the objects, for example, it may be better to implement a static function that iterates through the map of elements, rather than getting the map and then doing the iterations "outside".
Why:
I've never used this method myself, but one potential use case I can think of is e.g. in a graphics or game application, where you may want to only draw objects that are in scope and change certain drawing-related properties of all of them at once, e.g. color or size. I'm working on an application that might eventually need something like this (sort of a visual debugger). I'm sure people can provide more examples in the comments.
Why not:
The picture gets complicated when inheritance is involved.
If you have a class B that derives from A (i.e. B "is an" A), then who should keep track of objects of B? A static member of objects in A, or a similar one in B, or both?
Let's say both. Then what happens if a static function that applies to all objects in A calls a virtual member function on each object? If the virtual function has been overridden in the derived class, then that function will be called instead for all objects being tracked in class A that are actually B objects. What happens if you then call that function again in another static function in B?
There is no way that I know of but you can implement one with static members
#include <iostream>
#include <vector>
class MyClass{
private:
static std::vector<MyClass*> objList;
public:
MyClass() {
objList.push_back(this);
}
static std::vector<MyClass*> getAllObjects(){
return objList;
}
};
std::vector<MyClass*> MyClass::objList;
main(){
MyClass m,a;
for (int i=0;i<MyClass::getAllObjects().size();i++){
std::cout<<MyClass::getAllObjects()[i]<<std::endl;
}
}
No, unless you implement this mechanism yourself. By default it is not provided by C++ language.
You CAN implement this mechanism yourself quite easily - register class in some kind of table within constructor, unregister within destructor. As long as you follow rule of Three, it'll work fine.
Of course there is. Just use Factory pattern to create and destroy all your objects and, in Factory implementation, return a collection of live objects in a Factory function that you will provide.
As has already been stated C++ does not provide a mechanism to do this automatically. However (again has already been stated in the comments) you can use one of the standard library containers to maintain a list of created objects and then register them in the constructor and unregister them in the destructor. The example below shows one way to do this...
#include <iostream>
#include <memory>
#include <utility>
#include <map>
#include <algorithm>
#include <iterator>
#include <typeinfo>
#include <vector>
class Object
{
static std::map<const Object*, Object*> objects_;
public:
Object()
{
objects_.insert(std::make_pair(this, this));
}
virtual ~Object()
{
objects_.erase(this);
}
static std::vector<Object*> get_all()
{
std::vector<Object*> o;
o.reserve(objects_.size());
for (auto obj : objects_)
{
o.push_back(obj.second);
}
return std::move(o);
}
template<class Type>
static std::vector<Type*> get_bytype()
{
std::vector<Type*> o;
for(auto obj : objects_)
{
Type *t = dynamic_cast<Type*>(obj.second);
if (t != nullptr)
{
o.push_back(t);
}
};
return std::move(o);
}
void print() const
{
std::cout << "I'm a " << typeid(*this).name() << " object # " << this << std::endl;
}
};
std::map<const Object*, Object*> Object::objects_;
class Foo : public Object {};
class Bar : public Object {};
int main()
{
std::unique_ptr<Object> o1 = std::unique_ptr<Object>(new Foo());
std::unique_ptr<Object> o2 = std::unique_ptr<Object>(new Bar());
std::unique_ptr<Object> o3 = std::unique_ptr<Object>(new Foo());
std::unique_ptr<Object> o4 = std::unique_ptr<Object>(new Bar());
std::vector<Object*> objects = Object::get_all();
for (auto o : objects)
{
o->print();
}
std::cout << "-----" << std::endl;
std::vector<Foo*> foos = Object::get_bytype<Foo>();
for (auto o : foos)
{
o->print();
}
std::cout << "-----" << std::endl;
std::vector<Bar*> bars = Object::get_bytype<Bar>();
for (auto o : bars)
{
o->print();
}
}
The above example produces the following output
I'm a class Foo object # 003FED00
I'm a class Bar object # 003FED30
I'm a class Foo object # 003FED60
I'm a class Bar object # 003FED90
I'm a class Foo object # 003FED00
I'm a class Foo object # 003FED60
I'm a class Bar object # 003FED30
I'm a class Bar object # 003FED90
I have an object, BagOfThings, that stores a set of Things and a list of BagOfThingsListeners, which want to know when a Thing is added or removed from the BagOfThings they've been added to. Like this:
class Thing;
class BagOfThings;
class BagOfThingsListener {
public:
virtual ~BagOfThingsListener() {}
virtual void thingAdded(std::shared_ptr<BagOfThings> bag, std::shared_ptr<Thing> thing)=0;
virtual void thingRemoved(std::shared_ptr<BagOfThings> bag, std::shared_ptr<Thing> thing)=0;
};
class BagOfThings: public enable_shared_from_this<BagOfThings> {
private:
std::set<std::shared_ptr<Thing>> things;
std::list<std::shared_ptr<BagOfThingsListener>> listeners;
private:
BagOfThings() {}
public:
static std::shared_ptr<BagOfThings> create() {
return std::shared_ptr<BagOfThings>(new BagOfThings());
}
void addThing(std::shared_ptr<Thing> thing) {
things.insert(thing);
for (auto it=begin(listeners); it!=end(listeners); ++it) {
(*it)->thingAdded(shared_from_this(), thing);
}
}
void removeThing(std::shared_ptr<Thing> thing) {
things.erase(thing);
for (auto it=begin(listeners); it!=end(listeners); ++it) {
(*it)->thingRemoved(shared_from_this(), thing);
}
}
~BagOfThings() {
for (auto it=begin(things); it!=end(things);) {
auto currentIt=it++;
auto ¤tThing=*currentIt;
things.erase(currentIt);
for (auto it2=begin(listeners); it2!=end(listeners); ++it2) {
(*it2)->thingRemoved(shared_from_this(), currentThing);
}
}
}
};
This works fine except for the destructor, which is invalid as you're not allowed to use shared_from_this() when all shared_ptrs have been destroyed, which they have by the time the destructor is called. In this case I'm using shared pointers, but it seems to me that handing out the this pointer from the destructor is problematic anyway - someone might store the pointer, for instance. But in this case (wanting to let listeners know on destruction of the removal of all elements), I can't see an obvious nice way of doing it, without removing the pointer to the caller from the listener (i.e. thingAdded would become void thingAdded(std::shared_ptr<Thing>)).
Any ideas?
Why does BagOfThingsListener::thingAdded and BagOfThingsListener::thingRemoved need to take a shared_ptr? Would not a reference/const reference to BagOfThings be enough? When BagOfThings calls thingAdded or thingRemoved, you know that the this pointer is valid, so a reference will thus also be valid.
What are the ways in C++ to handle a class that has ownership of an instance of another class, where that instance could potentially be of a number of classes all of which inherit from a common class?
Example:
class Item { //the common ancestor, which is never used directly
public:
int size;
}
class ItemWidget: public Item { //possible class 1
public:
int height;
int width;
}
class ItemText: public Item { //possible class 2
std::string text;
}
Let's say there is also a class Container, each of which contains a single Item, and the only time anyone is ever interested in an Item is when they are getting it out of the Container. Let's also say Items are only created at the same time the Container is created, for the purpose of putting them in the Container.
What are the different ways to structure this? We could make a pointer in Container for the contained Item, and then pass arguments to the constructor of Container for what sort of Item to call new on, and this will stick the Items all in the heap. Is there a way to store the Item in the stack with the Container, and would this have any advantages?
Does it make a difference if the Container and Items are immutable, and we know everything about them at the moment of creation, and will never change them?
A correct solution looks like:
class Container {
public:
/* ctor, accessors */
private:
std::unique_ptr<Item> item;
};
If you have an old compiler, you can use std::auto_ptr instead.
The smart pointer ensures strict ownership of the item by the container. (You could as well make it a plain pointer and roll up your own destructor/assignment op/copy ctor/move ctor/ move assignment op/ etc, but unique_ptr has it all already done, so...)
Why do you need to use a pointer here, not just a plain composition?
Because if you compose, then you must know the exact class which is going to be composed. You can't introduce polymorphism. Also the size of all Container objects must be the same, and the size of Item's derived classes may vary.
And if you desperately need to compose?
Then you need as many variants of Container as there are the items stored, since every such Container will be of different size, so it's a different class. Your best shot is:
struct IContainer {
virtual Item& getItem() = 0;
};
template<typename ItemType>
struct Container : IContainer {
virtual Item& getItem() {
return m_item;
}
private:
ItemType m_item;
};
OK, crazy idea. Don't use this:
class AutoContainer
{
char buf[CRAZY_VALUE];
Base * p;
public:
template <typename T> AutoContainer(const T & x)
: p(::new (buf) T(x))
{
static_assert(std::is_base_of<Base, T>::value, "Invalid use of AutoContainer");
static_assert(sizeof(T) <= CRAZY_VAL, "Not enough memory for derived class.");
#ifdef __GNUC__
static_assert(__has_virtual_destructor(Base), "Base must have virtual destructor!");
#endif
}
~AutoContainer() { p->~Base(); }
Base & get() { return *p; }
const Base & get() const { return *p; }
};
The container requires no dynamic allocation itself, you must only ensure that CRAZY_VALUE is big enough to hold any derived class.
the example code below compiles and shows how to do something similar to what you want to do. this is what in java would be called interfaces. see that you need at least some similarity in the classes (a common function name in this case). The virtual keyword means that all subclasses need to implement this function and whenever that function is called the function of the real class is actually called.
whether the classes are const or not doesn't harm here. but in general you should be as const correct as possible. because the compiler can generate better code if it knows what will not be changed.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
class outputter {
public:
virtual void print() = 0;
};
class foo : public outputter {
public:
virtual void print() { std::cout << "foo\n"; }
};
class bar : public outputter {
public:
virtual void print() { std::cout << "bar\n"; }
};
int main(){
std::vector<outputter *> vec;
foo *f = new foo;
vec.push_back(f);
bar *b = new bar ;
vec.push_back(b);
for ( std::vector<outputter *>::iterator i =
vec.begin(); i != vec.end(); ++i )
{
(*i)->print();
}
return 0;
}
Output:
foo
bar
Hold a pointer (preferably a smart one) in the container class, and call a pure virtual clone() member function on the Item class that is implemented by the derived classes when you need to copy. You can do this in a completely generic way, thus:
class Item {
// ...
private:
virtual Item* clone() const = 0;
friend Container; // Or make clone() public.
};
template <class I>
class ItemCloneMixin : public Item {
private:
I* clone() const { return new I(static_cast<const I&>(*this); }
};
class ItemWidget : public ItemCloneMixin<ItemWidget> { /* ... */ };
class ItemText : public ItemCloneMixin<ItemText> { /* ... */ };
Regarding stack storage, you can use an overloaded new that calls alloca(), but do so at your peril. It will only work if the compiler inlines your special new operator, which you can't force it to do (except with non-portable compiler pragmas). My advice is that it just isn't worth the aggravation; runtime polymorphism belongs on the heap.