I have edited this from my real code, so that it is a little easier to understand.
The base class:
class MWTypes
{
public:
virtual long get() { return (0); }
};
The derived class: (There are going to be other classes like char, double etc etc . . .)
class TypeLong : public MWTypes
{
public:
TypeLong(long& ref) : m_long(ref) {}
~TypeLong();
long get() { return m_long; }
private:
long& m_long;
};
and the storage class:
class RowSet
{
public:
void addElememnt(MWTypes elem);
MWTypes getElement();
std::vector<MWTypes> getVector() { return m_row; }
private:
std::vector<MWTypes> m_row;
};
How it is called:
for (i = 0; i < NumCols; i++) // NumCols is 3 on this instance
{
switch(CTypeArray[i]) // this is an int which identifies the type
{
case SQL_INTEGER:
{
long _long = 0;
TypeLong longObj(_long);
MWTypes *ptr = &longObj;
// some SQL code goes here that changes the value of _long,
// there is no need to include it, so this will do.
_long++;
// I now want to save the data in a vector to be returned to the user.
rowSet.addElememnt(*ptr);
///////////////////////////////////////////////
// some code happens here that is irrelevant //
///////////////////////////////////////////////
// I now want to return the typr I have saved in the vector,
// I THINK I am doing this right?
MWTypes returned = rowSet.getElement();
// lastly I want to get the value in the returned type
long foo = returned.get();
///////////////////////////////////////////////
// some code happens here that is irrelevant //
///////////////////////////////////////////////
I think I am on the right lines here. The value of 'foo' is always 0. I have a feeling this could be the way Im storing in the vector, or it could be the base virtual function, as it always returns 0.
If I remove the return in my base class I get LNK2001 errors.
MWTypes returned = rowSet.getElement();
// lastly I want to get the value in the returned type
long foo = returned.get();
should be
MWTypes* returned = &rowSet.getElement();
// lastly I want to get the value in the returned type
long foo = returned->get();
or
MWTypes& returned = rowSet.getElement(); // actually illegal, but MSVC will let you do
// lastly I want to get the value in the returned type
long foo = returned.get();
Indeed, polymorphic calls must be made via a pointer or a reference.
EDIT: this is not your only problem. The fact that the vector stores objects (and not pointers) will slice the objects and destroy their type information.
See this faq entry for additional info to help you solve your problem and understand how virtual functions are called.
The fundamental problem is that you are making copies of your objects of type MWTypes, thus losing their particular subclass. If you want to use an object of an unknown subclass of the base class, then you can only use a pointer or reference to the base type, not an actual instance of it.
Not providing an implementation of the function "get" as ascanio's code shows (making the function "pure virtual") would prevent you from being able to make this copying mistake, because the compiler would not let you instantiate the class MWTypes if you did that (it would say the class is "abstract").
You are suffering from slicing since your collection stores copies of the base type. Whenever you store something into the vector, your code just slices off the base part and it forgets its original type.
To fix this, you could store pointers to the base: std::vector<MWTypes*>, but then you have to manage your instances correctly to avoid memory leaks.
class RowSet
{
public:
// addElement assumes responsibility for the memory allocated for each 'elem'
void addElement(MWTypes* elem);
MWTypes* getElement();
std::vector<MWTypes*> getVector() { return m_row; }
// Destructor calls delete on every pointer in m_row
~RowSet();
private:
std::vector<MWTypes*> m_row;
};
Then you need to fix your code which calls addElement() to create new instances, and to get the long back again:
rowSet.getElement()->get();
You're problem lies with this function void addElememnt(MWTypes elem);. It should be either void addElememnt(MWTypes* elem); or void addElememnt(MWTypes& elem);. This is because by having an argument to be passed by-value, it loses it's polymorphism. The passing by-value calls the copy constructor of the base class and ONLY copies the contents of the base class (and the vtable) ignoring the rest from the derived class.
Also, if you need to store values of a certain base-class type, you need to consider using a list of pointers of the base-class type.
The problem lies here:
class RowSet
{
public:
void addElememnt(MWTypes elem);
You are taking elem by value, not by pointer or by reference, so the TypeLong subobject is sliced away, here: (reference: What Is The Slicing Problem in C++?)
TypeLong longObj(_long);
MWTypes *ptr = &longObj;
_long++;
rowSet.addElememnt(*ptr);
You need to change addElement to take a reference or a pointer.
Your vector, getElement, and addElememnt parts all invoke object slicing since they store the base object by value. You need to work with pointers or references in order to use runtime polymorphism.
In this case either a boost::ptr_vector or a vector of shared_ptr is probably what you want.
Related
I've found out that unique_ptr can point to an already existing object.
For example, I can do this :
class Foo {
public:
Foo(int nb) : nb_(nb) {}
private:
int nb_;
};
int main() {
Foo f1(2);
Foo* ptr1(&f1);
unique_ptr<Foo> s_ptr1(&f1);
return 0;
}
My question is :
If I create a class with unique_ptr< Bar > as data members (where Bar is a class where the copy constructor was deleted) and a constructor that takes pointers as argument, can I prevent the user from passing an already existing object/variable as an argument (in that constructor) (i.e. force him to use the new keyword) ?
Because if he does, I won't be able to guarantee a valide state of my class objects (the user could still modify data members with their address from outside of the class) .. and I can't copy the content of Bar to another memory area.
Example :
class Bar {
public:
Bar(/* arguments */) { /* data members allocation */ }
Bar(Bar const& b) = delete;
/* Other member functions */
private:
/* data members */
};
class Bar_Ptr {
public:
Bar_Ptr(Bar* ptr) {
if (ptr != nullptr) { ptr_ = unique_ptr<Bar> (ptr); }
} /* The user can still pass the address of an already existing Bar ... */
/* Other member functions */
private:
unique_ptr<Bar> ptr_;
};
You can't prevent programmers from doing stupid things. Both std::unique_ptr and std::shared_ptr contain the option to create an instance with an existing ptr. I've even seen cases where a custom deleter is passed in order to prevent deletion. (Shared ptr is more elegant for those cases)
So if you have a pointer, you have to know the ownership of it. This is why I prefer to use std::unique_ptr, std::shared_ptr and std::weak_ptr for the 'owning' pointers, while the raw pointers represent non-owning pointers. If you propagate this to the location where the object is created, most static analyzers can tell you that you have made a mistake.
Therefore, I would rewrite the class Bar_ptr to something like:
class Bar_ptr {
public:
explicit Bar_ptr(std::unique_ptr<Bar> &&bar)
: ptr(std::move(bar)) {}
// ...
}
With this, the API of your class enforces the ownership transfer and it is up to the caller to provide a valid unique_ptr. In other words, you shouldn't worry about passing a pointer which isn't allocated.
No one prevents the caller from writing:
Bar bar{};
Bar_ptr barPtr{std::unique_ptr<Bar>{&bar}};
Though if you have a decent static analyzer or even just a code review I would expect this code from being rejected.
No you can't. You can't stop people from doing stupid stuff. Declare a templated function that returns a new object based on the templated parameter.
I've seen something similar before.
The trick is that you create a function (let's call it make_unique) that takes the object (not pointer, the object, so maybe with an implicit constructor, it can "take" the class constructor arguments) and this function will create and return the unique_ptr. Something like this:
template <class T> std::unique_ptr<T> make_unique(T b);
By the way, you can recommend people to use this function, but no one will force them doing what you recommend...
You cannot stop people from doing the wrong thing. But you can encourage them to do the right thing. Or at least, if they do the wrong thing, make it more obvious.
For example, with Bar, don't let the constructor take naked pointers. Make it take unique_ptrs, either by value or by &&. That way, you force the caller to create those unique_ptrs. You're just moving them into your member variables.
That way, if the caller does the wrong thing, the error is in the caller's code, not yours.
So, I have the feeling that this is a bad idea:
class Foo
{
public:
Foo(const Foo& from)
{
memcpy(this, &from, sizeof(Foo));
m_someData = new int[m_dataLength];
memcpy(m_someData, from.m_someData, m_dataLength * sizeof(int));
}
private:
int* m_someData;
int m_dataLength;
};
The question is: why? If the memcpy parameters are the same type (and size), with identical layout, where's the bad?
One potential issue I see is if there is a string or vector<> field, but I'm not sure if that's a valid concern.
If Foo can be derived from, consider what happens when you have a Bar class derived from Foo, and copy-construct a Foo from that Bar instance.
If you have any virtual methods, your sizeof(Foo) includes any information added by the compiler to implement virtual methods (meaning the vtable), which you definitely don't want to copy.
If you don't have any virtual methods, but Bar adds a field to Foo, then you still have a potential problem: that field can be stored in the padding bytes of Foo. They would be clobbered by a memcpy.
Finally:
One potential issue I see is if there is a string or vector<> field, but I'm not sure if that's a valid concern.
Why wouldn't it be? It would clearly break, and it would break badly.
You can avoid this problem by using the default automatically generated copy constructor. If you want to add logic to that, and not be forced to mention all fields you want to copy, use a hidden data container:
class Foo
{
public:
Foo(const Foo& from)
{
m_Data = from.m_Data;
m_Data.m_someData = new int[m_Data.m_dataLength];
memcpy(m_Data.m_someData, from.m_Data.m_someData, m_Data.m_dataLength * sizeof(int));
}
private:
struct Data {
int* m_someData;
int m_dataLength;
// more fields
};
Data m_Data;
};
Note how m_Data = from.m_Data; here has the exact effect you were trying to achieve with the memcpy, except it does it safely.
why it's wrong:
struct boom1 {
boom1(const boom1& from)
// reason 1: not using an initialisation list means double-initialisation of members. inefficient.
{
// reason 2: undefined behaviour on all subsequent access to
// this->_s or from._s after this line
memcpy(this, &from, sizeof(from));
// reason 3: what if someone derived from this class? didn't you just overwrite the RTTI info pointer??
}
// reason 4: c++ already generates a copy constructor that does the right thing automatically. why are you laying mines for other developers?
std::string _s;
}
"yes but my particular class is a POD and I'm in control of it"...
... until someone else derives from it, modifies it or tries to maintain it.
no, no, no. This is never right. always wrong. make sure your student understands this. One day he may be programming a google car. You wouldn't want it to run over your kids now would you?
I want to implement class which let's say have field key and class A or B.
The argument in constructor in this class is array of chars.
The constructor pseudocode would take a look at first char, if it is exual to 0x00 it will create class A object,
otherwise it will create class B object - both classes will take the array of chars as argument.
Anyway I want to keep this implementation simple. I don't want to use boost::Variant unless I really need to,
and also I don't want to implement sth like this Implementing a "variant" class
because I am not familiar with template programming and I think my problem can be implemented in much simpler way.
For POD types, we have union (but the union won't remember which type you assigned, so also store this separately). This won't work for non-POD types. The major reason is because C++ doesn't know which one it should create upon construction / delete upon deletion of the union.
But a union can be used to hold pointers to the actual types. Then you have to care about construction and deletion yourself.
You could create something like this, which wraps this pointer-union and adds a convenient interface. Detailed explanation is written in the comments:
class EitherAorB {
// We have to remember what we actually created:
enum Which {
A_Type,
B_Type
} m_which;
// We store either a pointer to an A or to a B. Note that this union only
// stores one pointer which is reused to interpret it as an A*, B* or void*:
union {
A *a;
B *b;
void *untyped; // Accessing the same pointer without looking at the type
} m_ptr;
// Additional stuff you want to store besides A and B
const char *m_key;
public:
EitherAorB(const char *key) {
// Decision: Which type do we want to create?
m_which = key[0] == 0 ? A_Type : B_Type;
// Create the type (the cast to void* make the pointer "untyped"):
m_ptr.untyped = m_which == A_Type ? (void*)new A() : (void*)new B();
// Store additional stuff
m_key = key;
}
~EitherAorB() {
// Since we stored the actual contents outside and point to them,
// we have to free the memory. For this, we have to care about the
// type again, so the correct destructor will be chosen. Deleting
// the untyped pointer won't work here.
if (m_which == A_Type) delete m_ptr.a;
if (m_which == B_Type) delete m_ptr.b;
}
// These two functions can be used to query which type is stored.
bool hasA() const {
return m_which == A_Type;
}
bool hasB() const {
return m_which == B_Type;
}
// These two functions can be used to query the pointers to the actual types.
// I made them return a null pointer if the wrong getter was used.
A *getA() {
return m_which == A_Type ? m_ptr.a : 0;
}
B *getB() {
return m_which == B_Type ? m_ptr.b : 0;
}
}
Note that this implementation will lack memory if you copy an instance of EitherAorB. To fix this, either disable copying (by making the copy constructor and assignment operator private or disable them in C++11 using = delete), or implement the copy constructor and assignment operator which will deeply copy the pointee.
You said you aren't familiar with template programming. Making this implementation templated isn't difficult. Just put template<typename A, typename B> before the whole class definition; it should then work out of the box. However, don't move the implementations in .cpp files in this case; best is to keep them inlined as I wrote it.
Then, A and B aren't types but placeholders you assign types in your client code. I'd then rename the tempalte class to just Either, so your type names become something like Either<This, That>.
Here is part of my code:
class A
{
public:
void init(classB& pObject);
classB& _pObject;
}
void classA::init(classB& pObject)
{
_pObject = pObject;
}
class B
{
public:
void init();
}
void classB::init()
{
classA* pClassA = new classA;
pClassA->init(&this);
}
I got 2 problems after compile:
_pObject = pObject;: No viable overloaded '='
pClassA->init(&this);: Address expression must be an lvalue or a function designator
I'm getting confused about these problems... How can I fix that?
First, there is a typo in the question. I assume that A and classA refer to the same class, ditto for B and classB.
1) One of the few differences between a reference and a pointer is that you cannot assign a different value to a reference once it's been initialised. So you just cannot assign to _pObject, though you can initialise it in the initialisation list of the constructor for class A:
classA::classA(classB& object) : _pObject(object) // Correct
{
// _pObject = object; on the other hand, this would be incorrect
}
2) &this is the address of this, but you actually want a reference to the value pointed to by this. You need to use *this instead. Though we have already seen that there is no way to make function classA::init work with your current class design. If you really want to change the value of _pObject after the object has been constructed, you need to make it a classB* instead of a classB&.
1) You should use *this in this context, as &this has the type of ClassB**, not ClassB&;
2) You can only initialize you reference member-variables in constructor:
classA::classA(classB& b) : _pObject(b)
{
}
(BTW I suppose that you ommitted delete statement just for brevity)
I am new here.
I am also new on C++
So here is the class and function i wrote.But i got the compiler error
My class:
class fooPlayer
{
public:
void fooPlayerfunc(){}//doing something here
char askYesNo(std::string question);
};
class fooPlayerFactory
{
public:
virtual std::auto_ptr<fooPlayer> MakePlayerX() const;
virtual std::auto_ptr<fooPlayer> MakePlayerO() const;
private:
std::auto_ptr<fooPlayer> MakePlayer(char letter) const;
std::auto_ptr<fooPlayer> my_player;
};
Implement my class:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerX() const
{
char go_first = my_player->askYesNo("Do you require the first move?");
MakePlayer(go_first);
return my_player;
}
auto_ptr<fooPlayer> fooPlayerFactory::MakePlayerO() const
{
return my_player;
}
My main() function here:
int main()
{
fooPlayerFactory factory;
factory.MakePlayerX();
factory.MakePlayerO();
}
I got the error:
error C2558: class 'std::auto_ptr<_Ty>' : no copy constructor available or copy constructor is declared 'explicit'
I do not know how to change it even after reading the document on this link:
The reason for the error is that you are calling the copy constructor of auto_ptr my_player in fooPlayerFactory::MakePlayerO() which is a const method. That means that is cannot modify its members.
However the copy constructor of auto_ptr DOES modify the right hand side so returning my_player trys to change its pointer to 0 (NULL), while assigning the original pointer to the auto_ptr in the return value.
The signature of the copy constuctor is
auto_ptr<T>::auto_ptr<T>(auto_ptr<T> & rhs)
not
auto_ptr<T>::auto_ptr<T>(const auto_ptr<T> & rhs)
The copy constructor of auto_ptr assigns ownership of the pointer to the left hand side, the right hand side then holds nothing.
I don't think you want to use auto_ptr here, you probably want boost::smart_ptr
It looks like you have mixed up two uses for auto_ptr
The first is as poor man's boost::scoped_ptr. This is to manage a single instance of a pointer in a class, the class manages the life time of the pointer. In this case you don't normally return this pointer outside your class (you can it is legal, but boost::smart_ptr / boost::weak_ptr would be better so clients can participate the life time of the pointer)
The second is its main purpose which is to return a newly created pointer to the caller of a function in an exception safe way.
eg
auto_ptr<T> foo() {
return new T;
}
void bar() {
auto_ptr<T> t = foo();
}
As I said I think you have mixed these two uses auto_ptr is a subtle beast you should read the auto_ptr docs carefully. It is also covered very well in Effective STL by Scott Meyers.
In your code:
auto_ptr<fooPlayer> fooPlayerFactory:: MakePlayer(char letter) const
{
my_player->fooPlayerfunc();
return my_player;
}
This is a const function, but fooPlayerfunc is not const - my compiler reports this error rather than the one you say you are getting. Are you posting the real code?
I don't think you actually want to constructing dynamic objects here.
A factory object creates and returns an object it normally does not keep a reference to it after creation (unless you are sharing it), and I don't actually see anywhere that you are creating the player.
If you only ever create one player internally in your (fooPlayerFactory). Then create an object and return references to it.
Edit: in response to the comment (which is correct, my bad), I left only the advice part.
Best practice is to have the factory methods just return a plain old pointer to the underlying object, and let the caller decide how to manage ownership (auto_ptr, scoped_ptr, or whatever).
Also your code is buggy, any class that implements virtual methods should have a virtual destructor.
I'm not seeing anywhere you construct my_player, so I have a feeling that some of the code is missing. Specifically, I think your constructor has this line:
my_player = new fooPlayer()
A fooPlayer object is not quite the same thing as an auto_ptr<fooPlayer> object, and auto_ptr is intentionally designed to prevent assigning from one to the other because, frankly, the alternative is worse. For the details, look up (1) conversion constructors, (2) the explicit keyword, and (3) copy constructors and destructive copy semantics.
You should change the constructor to either:
class fooPlayerFactory {
public:
fooPlayerFactory()
{
my_player = std::auto_ptr<fooPlayer>(new fooPlayer());
}
Or (using a member initializer list):
class fooPlayerFactory {
public:
fooPlayerFactory() : my_player(std::auto_ptr<fooPlayer>(new fooPlayer()) { }
The solution isn't pretty but, like I said, the alternative is worse due to some really arcane details.
As a bit of advice, though, you're making life harder than it needs to be; and may in fact be causing strange bugs. auto_ptr exists to manage the lifetime of an object, but the only reason you need to worry about the lifetime of my_player is that you've allocated it with new. But there's no need to call new, and in fact there's no need to keep my_player. And unless fooPlayerFactory is meant to be the base class for some other factory, there's no need to mark functions virtual.
Originally I thought you could get away with simply returning copies of the my_player object, but there's a problem: before returning my_player from MakePlayer() you call a method on it, and I assume that method changes the internal state of my_player. Further calls to MakePlayer() will change the state again, and I think you're going to eventually have my_player in the wrong state. Instead, return a different fooPlayer object with each request. Don't do memory management, just promise to construct the object. That way the user can decide on memory allocation:
fooPlayerFaclotry factory;
fooPlayer on_stack = factory.MakePlayerX();
fooPlayer* on_heap_raw_pointer = new fooPlayer(factory.MakePlayerO());
std::auto_ptr<fooPlayer> on_heap_managed_scope
= std::auto_ptr<fooPlayer>(factory.MakePlayerX());
I would change fooPlayerFactory to look like this:
class fooPlayerFactory
{
private:
fooPlayer MakePlayer(const char letter) const
{
fooPlayer result;
result.fooPlayerfunc();
return result;
}
public:
fooPlayer* MakePlayerX() const
{
char go_first = askYesNo("Do you require the first move?");
return MakePlayer(go_first);
}
fooPlayer MakePlayerO() const
{
return fooPlayer();
}
};