I have a class Model:
class Model
{
...
boost::shared_ptr<Deck> _deck;
boost::shared_ptr<CardStack> _stack[22];
};
Deck inherits from CardStack.
I tried to make _stack[0] point to the same thing that _deck points to by going:
{
_deck = boost::shared_ptr<Deck>(new Deck());
_stack[0] = _deck;
}
It seems that the assignment to _deck of _stack[0] results in a copy of _deck being made. (I know this because modifications to _stack[0] do not result in modifications to _deck.) How can I get them to point to the same thing?
Ok - no copy constructor is being called. I have verified this by implementing it and seeing if it gets called - it doesn't.
However - I have a function that operates on CardStack objects:
void TransferSingleCard(CardStack & src, CardStack & dst, Face f)
{
if( !src._cards.empty() )
{
src._cards.back().SetFace(f);
dst.PushCard(src._cards.back());
src._cards.pop_back();
}
}
Now - when I call:
{
TransferSingleCard(*_stack[DECK], _someotherplace, FACEDOWN);
std::cout << *_stack[DECK];
std::cout << *_deck;
}
I get this output (where std::cout on a CardStack will print out the size of that stack):
Num(103) TOP
Num(104) TOP
... so I've concluded (incorrectly?) that _stack[DECK] points to something different.
The Deck
class Deck : public CardStack
{
public:
Deck(int numsuits=2, StackIndex index = NO_SUCH_STACK );
Deck::Deck( const Deck & d);
int DealsLeft() const;
void RecalcDealsLeft();
private:
int _dealsleft;
};
Not clear what you are asking about - consider this code:
#include <iostream>
#include "boost/shared_ptr.hpp"
using namespace std;
struct A {
virtual ~A() {
cout << "destroyed" << endl;
}
};
struct B : public A {
};
int main() {
boost::shared_ptr<B> b( new B );
boost::shared_ptr<A> a;
a = b;
}
Only one "destroy" message appears, indicating that no copy has been made.
This example - derives from #Neil's answer, tries to emulate what you say is happening. Could you check that it works as expected (A and B have the same count) on your system.
Then we could try and modify this code or your code until they match.
#include <boost/shared_ptr.hpp>
#include <iostream>
class A {
public:
virtual ~A()
{
std::cerr << "Delete A" << std::endl;
}
int _count;
void decrement()
{
_count --;
}
};
class B : public A {
public:
virtual ~B()
{
std::cerr << "Delete B" << std::endl;
}
};
int main()
{
boost::shared_ptr<B> b(new B);
b->_count = 104;
boost::shared_ptr<A> a;
a = b;
a->decrement();
std::cerr << "A:" << a->_count << std::endl;
std::cerr << "B:" << b->_count << std::endl;
return 0;
}
EDIT:
So from the comment, we know the original pointers are correct, so now we need to trace.
Either:
log pointers to see when they change.
Use watchpoints in a debugger to see when the pointer changes.
Use a third shared pointer to see which pointer is changed.
Introduce a function that changes both pointers at the same time.
I think the problem is that you're assigning between different types here. boost::shared_ptr is a template and templates are not polymorphic even if the type in them is. So what's happening is that your compiler sees the assignment from boost::shared_ptr<Deck> to boost::shared_ptr<CardStack> and notices that it can make the assignment by calling the copy constructor for CardStack to duplicate the Deck object.
I think what you want the assignment to look like is something like this:
_stack[0] = boost::static_pointer_cast<CardStack>(_deck);
Which will do the conversion the way you expect it to.
I think you may want shared_array for _stack . . . Take a look at the documentation on shared_ptr;from boost.org, specifically:
http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm
"Normally, a shared_ptr cannot
correctly hold a pointer to a
dynamically allocated array. See
shared_array for that usage."
Also, be aware of the T* get() function (not to be used without good reason) which returns the raw pointer being held by the managed pointer (shared_ptr in this case).
Related
So lets say I have
class A
{
A(std::vector<std::shared_pointer<A>> &a_vec)
{
auto shared_ptr = std::make_shared<A>(*this);
a_vec.pushback<shared_ptr>;
{
};
class B
{
std::vector<std::shared_pointer<A>> a_vector_;
void constructA()
{
created_A = make_shared<A>(a_vector_);
}
}
So Im creating a method for B which creates an A and the A pushes itself to the vector B provides.
And on paper this dependancy works like I expected to, atleast I thought it was until I realised the a_vec.pushback<this*>; is not very dependable.
When I have more code inbetween the push and the shared pointer initialisation as such
A(std::vector<std::shared_pointer<A>> a_vec)
{
auto shared_ptr = std::make_shared<A>(*this);
//insert more code here
a_vec.pushback<shared_ptr>;
{
It seems that the initialisations and other stuff I do in there isn't reflected to the pointer the shared pointer is pointing. Whats the cause of this and is there a way to fix it? Also is there a reason this would be a bad practice to use?
One of the challenges when you are programming in C++ is to understand object lifetime. So it is better to make object creation and destruction as clear as possible.
As I understood your case is to memoize "automagically" all created objects. It is easier to do using "factory method" constructA
#include <iostream>
#include <vector>
#include <memory>
class A
{
public:
A() = default;
};
class B//AInstanceFactory - is a better name
{
std::vector<std::shared_ptr<A>> a_instances;
public:
void constructA()
{
a_instances.push_back(std::make_shared<A>());
}
const std::vector<std::shared_ptr<A>>& getAInstances() {
return a_instances;
}
};
int main()
{
B b;
b.constructA();
std::cout << b.getAInstances().size() << "\n";
b.constructA();
std::cout << b.getAInstances().size() << "\n";
}
[WRONG PATH]
It is possible to make object which aware of shared_ptr/weak_ptr: use template std::enable_shared_from_this.
In that case your code might be following,:
#include <iostream>
#include <vector>
#include <memory>
class A : std::enable_shared_from_this<A>
{
public:
A(std::vector<std::shared_ptr<A>>& a_vec)
{
a_vec.push_back(shared_from_this());//bad_weak_ptr here!!!!
}
};
class B
{
std::vector<std::shared_ptr<A>> a_vector_;
public:
void constructA()
{
auto a_ptr = make_shared<A>(a_vector_);
}
const std::vector<std::shared_ptr<A>>& getAVec() {
return a_vector_;
}
};
int main()
{
B b;
b.constructA();
std::cout << b.getAVec().size() << "\n";
}
BUT it wrong, because underlying weak_ptr is "ready" only after function make_shared is executed, means only after construction call.
Calling shared_from_this or weak_from_this is valid only after make_shared function is executed.
I would like to perform a down casting at execution time.
For what I read, if I want to do it, I need to compare the typeid of my polymorphic pointer with those of my derived classes, then do the casting in the correct type.
Plus, let's assume that I have a large number of derived classes.
This implies I have to write a long switch or list of if.
I would like to reduce this effort by using a list of classes to check.
This could look like:
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
using namespace std;
class BaseShapes
{
virtual int run() = 0;
};
class ClassRectangle : public BaseShapes
{
int run()
{
std::cout << "I am a Rectangle. " << std::endl;
return 0;
}
float get_length () {return 12.4;};
float get_width() {return 6.2;};
};
class ClassCircle : public BaseShapes
{
int run()
{
std::cout << "I am a Cricle. " << std::endl;
return 0;
}
float get_diameter() {return 5.3;};
};
float function_only_for_Rectangle(ClassRectangle *rectangle)
{
// a function coming from a library that I cannot touch and that requires a derived type.
// But for the example I do something dummy!
return rectangle->get_length()
};
auto downcast_function (auto *p)
{
enum ListOfTypes {
ClassCircle,
ClassRectangle,
// and a lot more differents classes
};
for ( int fooInt = ClassCircle; fooInt < ClassRectangle; fooInt++ )
{
ListOfTypes fooItem = static_cast<ListOfTypes>(fooInt);
if (typeid(p) == typeid(fooItem))
{
auto pCasted =dynamic_cast<fooItem>(p);
return pCasted;
}
}
std::cout<< "downcast_function warning: no typeid is matching !" << std::endl;
return p;
};
int main(void)
{
// Beginning of main.
cout << "(Start)" << endl;
std::unique_ptr<BaseShapes> Shape1(new ClassRectangle());
auto p=Shape1.get();
//function_only_for_Rectangle(p); // not working since p is of type BaseShapes*
auto pbis=downcast_function(p); // should be of type ClassRectangle*
function_only_for_Rectangle(pbis);
// End of the main.
cout << "(End) " << endl;
return 0;
}
// EoF
So how can I write the downcast_function ? Or in other words, how can I iterate over a list of class types in order to make a typeid comparison and a casting ?
More details:
I agree that in this dummy example, I could simply override a function for each derived class and that is a much better way to deal with polymorphism. But I need to downcast, this is a constrain coming from a more complex problem where they are things that I am not allowed to changed. So, the question here is not why downcast but how.
To give a bit more details about my constrains are:
To start from a base pointer.
Get a derived pointer and give it to an external function (here called function_only_for_Rectangle, so I cannot modify this function).
I cannot do a simple and direct dynamic_cast<ClassRectangle>(p) because the type of p (or equivalently Shape1) will change at running time. This means that Shape1 can have "randomly" any derived type from BaseShapes. So I need something "automatic" and this is why I was thinking about iterate over all derived types and downcast according to the typeid match (but I am open to better ideas).
All the classes can modified if needed.
You say "polymorphic" but what you want to do is the opposite of it.
Instead of trying to work against polymorphism you could actually use it. If all subclasses have their own implementation of a virtual function then the caller does not need to care what the actual dynamic type of the object is. That is runtime polymorphism in a nutshell.
I suppose the naming for run is only for the example. Give it a better name, supply a default implementation in the base class, implement specific behavior in ClassRectangle and let the caller call it. No need to cast.
class BaseShapes
{
virtual int do_something_rectangly() { return 0;}
~virtual BaseShapes() = default;
};
class ClassRectangle : public BaseShapes
{
int do_something_rectangly() override
{
std::cout << "I am a Rectangle. " << std::endl;
return 0;
}
};
class ClassCircle : public BaseShapes
{
// does not override do_something_rectangly()
};
int function_for_any_base_shape(BaseShapes& s)
{
return s.do_something_rectangly();
};
int main(void)
{
// Beginning of main.
cout << "(Start)" << endl;
std::unique_ptr<BaseShapes> Rec1(new ClassRectangle());
function_for_any_base_shape(*pbis);
cout << "(End) " << endl;
return 0;
}
Concerning your edit:
I cannot do a simple and direct dynamic_cast(p) because the type of p (or equivalently Shape1) will change at running time. This means that Shape1 can have "randomly" any derived type from BaseShapes. [...]
Either I misunderstand what you wrote completely or you misunderstand how dynamic_cast works. dynamic_cast does already check what the dynamic type of the object is:
BaseShapes* b1 = new ClassCircle;
if(ClassRectangle* d = dynamic_cast<ClassRectangle*>(b1))
{
// cast is sucessfull
function_only_for_Rectangle(d);
} else {
// dynamic type of b1 is not ClassRectangle
}
To call function_only_for_Rectangle you do not need to be able to cast to all subtypes of ClassBase. You only need to dynamic_cast to a pointer to ClassRectangle and check if the cast was sucesfull.
I want to create a vector of "Act" objects that contain pointers to either "Eat" or "Drink" dynamically allocated objects. The new objects are being emplaced like so:
action_vector.emplace_back(Act::BehaviorType::eat);
However, it is seg-faulting and I can't figure out why. I thought that emplace_back would implicitly call the move constructor, not the destructor, but for some reason it is, which (I think) is what is screwing everything up.
Is there any way to successfully create a vector of such objects?
Here is the rest of the code along with its output. Sorry if it's a little verbose, but basically it's just a strategy pattern.
#include <iostream>
#include <vector>
class IBehavior
{
public:
IBehavior() = default;
virtual ~IBehavior() = default;
virtual void execute() = 0;
};
class Drink : public IBehavior
{
public:
Drink(): IBehavior() {}
~Drink() {}
void execute() { std::cout << "Drinking" << std::endl; }
};
class Eat : public IBehavior
{
public:
Eat(): IBehavior() {}
~Eat() {}
void execute() { std::cout << "Eating" << std::endl; }
};
class Act
{
IBehavior * b;
public:
enum class BehaviorType { eat = 0, drink = 1 };
Act() = default;
~Act()
{
std::cout << "Calling the destructor" << std::endl;
delete b;
}
Act(BehaviorType b_type) { SetBehavior(b_type); }
Act(Act&& act)
{
std::cout << "Calling the move constructor" << std::endl;
this->b = act.b;
}
void SetBehavior(BehaviorType b_type)
{
if(b_type == BehaviorType::eat) b = new Eat();
if(b_type == BehaviorType::drink) b = new Drink();
}
void execute() { b->execute(); }
};
int main(int argc, char * argv[])
{
std::vector<Act> action_vector;
for(int i = 0; i < 10; ++i)
{
action_vector.emplace_back(Act::BehaviorType::eat);
action_vector[i].execute();
}
return 0;
}
output:
Eating
Calling the move constructor
Calling the destructor
Eating
Calling the move constructor
Calling the move constructor
Calling the destructor
Calling the destructor
Segmentation fault: 11
Your move constructor copies b, and destructor deletes b, so if you move construct an instance then the same pointer value will be deleted twice which has undefined behaviour.
General solution: Use a smart pointer.
Another bug: Default constructor leaves b uninitialised. When a default constructed object is destroyed, the uninitialised pointer is deleted and behaviour is undefined. Smart pointer fixes this also.
To understand the problems with object slicing, I thought I have created a horrible example and I was trying to test it. However, the example is not as bad as I thought it would be.
Below is a minimal working example, and I would appreciate if you helped me understand why it is still "working properly". It would be even better if you helped me make the example worse.
#include <functional>
#include <iostream>
template <class T> class Base {
protected:
std::function<T()> f; // inherited
public:
Base() : f{[]() { return T{0}; }} {} // initialized
virtual T func1() const { return f(); }
virtual ~Base() = default; // avoid memory leak for children
};
template <class T> class Child : public Base<T> {
private:
T val;
public:
Child() : Child(T{0}) {}
Child(const T &val) : Base<T>{}, val{val} { // initialize Base<T>::f
Base<T>::f = [&]() { return this->val; }; // copy assign Base<T>::f
}
T func1() const override { return T{2} * Base<T>::f(); }
void setval(const T &val) { this->val = val; }
};
template <class T> T indirect(const Base<T> b) { return b.func1(); }
int main(int argc, char *argv[]) {
Base<double> b;
Child<double> c{5};
std::cout << "c.func1() (before): " << c.func1() << '\n'; // as expected
c.setval(10);
std::cout << "c.func1() (after): " << c.func1() << '\n'; // as expected
std::cout << "indirect(b): " << indirect(b) << '\n'; // as expected
std::cout << "indirect(c): " << indirect(c) << '\n'; // not as expected
return 0;
}
The output I get when I compile the code is as follows:
c.func1() (before): 10
c.func1() (after): 20
indirect(b): 0
indirect(c): 10
I would expect the last line to throw some exception or simply fail. When the base part of c gets sliced in indirect, there is no this->val to be used inside the lambda expression (I know, C++ is a statically compiled language, not a dynamic one). I have also tried capturing this->val by value when copy assigning Base<T>::f, but it did not change the result.
Basically, my question is two folds. First, is this undefined behaviour, or simply a legal code? Second, if this is a legal code, why is the behaviour not affected by slicing? I mean, I can see that T func1() const is called from the Base<T> part, but why is the captured value not causing any trouble?
Finally, how can I build an example to have worse side-effects such as memory access type of problems?
Thank you in advance for your time.
EDIT. I am aware of the other topic that has been marked as duplicate. I have read all the posts there, and in fact, I have been trying to duplicate the last post there. As I have asked above, I am trying to get the behaviour
Then the information in b about member bar is lost in a.
which I cannot get fully. To me, only partial information seems to be lost. Basically, in the last post, the person claims
The extra information from the instance has been lost, and f is now prone to undefined behaviour.
In my example, f seems to be working just as well. Instead, I just have the call to T Base<T>::func1() const, which is no surprise.
There is no undefined behavior with your current code. However, it's dangerous and therefore easy to make undefined behavior with it.
The slicing happen, and yet you access this->val. Seems like magic, but you're just accessing the this->val from Child<double> c from your main!
That's because of the lambda capture. You capture this, which points to your c variable in your main. You then assign that lambda into a std::function inside your base class. You base class now have a pointer to the c variable, and a way to access the val through the std::function.
So the slicing occurs, but you access to the unsliced object.
This is also why the number is not multiplied by two. The virtual call resolves to base, and the value of val in c in your main is 10.
Your code is roughly equivalent to that:
struct B;
struct A {
B* b = nullptr;
int func1() const;
};
struct B : A {
int val;
explicit B(int v) : A{this}, val{v} {}
};
int A::func1() const {
return b->val;
}
int main() {
B b{10};
A a = b;
std::cout << a.func1() << std::endl;
}
I created some code to reproduce the problem:
#include "stdafx.h"
#include <iostream>
#include <vector>
class A
{
protected:
int m_X;
public:
A() {
std::cout << "in A ctor" << std::endl;
m_X = 0;
}
virtual void printX(){ std::cout << "in A " << m_X << std::endl; }
};
class B : public A
{
public:
B() {
std::cout << "in B ctor" << std::endl;
m_X = 1;
}
virtual void printX(){ std::cout << "in B " << m_X << std::endl; }
};
class As
{
public:
void AddA( const A &a ){ m_As.push_back( a ); }
void PrintXs()
{
for ( auto a : m_As )
{
a.printX();
}
}
private:
std::vector<A> m_As;
};
int _tmain(int argc, _TCHAR* argv[])
{
As as;
B b;
as.AddA( b );
as.PrintXs();
system("pause");
return 0;
}
The output of this is:
in A ctor
in B ctor
in A 1
I want "in B 1" instead of "in A 1". I'm sure my understanding of virtual is flawed. How must I change the code to call the B PrintX()? Note that there will be other classes that inherit from A so I really don't want to code a static call.
Thanks.
What you're doing is called slicing. This is where you take an object of a derived class and trim off everything that is not in the parent and assign it to the parent.
What you want to do is use polymorphism to do what you explained. To do this, change your vector from a copy of the object, to a ptr to the object.
If interested in more details, please use the links provided, the information included in them seems to be very complete.
The quick fix is to change your As class to the following:
class As
{
public:
void AddA( A &a ){ m_As.push_back( &a ); }
void PrintXs()
{
for ( auto a : m_As )
{
a->printX();
}
}
private:
std::vector<A*> m_As;
};
When you use std::vector<A> m_As;, the vector can only fit A objects. If you use pointers instead then polymorphism can work and call the correct printX function. However, this has the problem of dangling pointer if the lifetime of the pointed to object expires. To handle that it would be better to use a smart pointer class like std::unique_ptr.
Since you're passing objects by value you can not take advantages of polymorphism. Pass them by (smart) pointers or references.
std::vector<std::shared_ptr<A>> m_As;
// or
std::vector<std::unique_ptr<A>> m_As;
// or
std::vector<A*> m_As; // be careful of bare pointers
// or (since C++11)
std::vector<std::reference_wrapper<A>> m_As;
std::reference_wrapper magic!
For the last one, you can use std::reference_wrapper and std::ref:
class As
{
public:
void AddA(A &a){ m_As.push_back( std::ref(a) ); }
void PrintXs() const
{
for ( auto a : m_As )
{
a.get().printX();
}
}
private:
std::vector<std::reference_wrapper<A>> m_As;
};
Using last code, you don't have to change main code.
Live code
for ( const auto & a : m_As )
{
a.printX();
}
it will keep you from expanded copy and provide the B-instance instead of A-instance, appeared as copy.