Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
i write a handle class using C++. But when i run my code, i met an error.
#pragma once
#include <iostream>
using std::cout;
using std::endl;
class BaseItem{
public:
virtual BaseItem* clone()
{
return new BaseItem(*this);
}
virtual void sayHello()
{
cout<<"Hello, I am class BaseItem!"<<endl;
}
};
class ChildItem:public BaseItem{
public:
ChildItem* clone()
{
return new ChildItem(*this);
}
void sayHello(){
cout<<"Hello, I am class ChildItem!"<<endl;
}
};
template <typename T>
class Handle
{
public:
Handle():baseItem(NULL), refCount(new size_t(0)) {}
Handle(T& object):baseItem(object.clone()), refCount(new size_t(1)) {}
Handle(const Handle<T>& other):baseItem(other.baseItem), refCount(new size_t(1)) {}
Handle& operator= (const Handle<T>& other)
{
++*other.refCount;
dec_count();
baseItem = other.baseItem;
refCount = other.refCount;
return *this;
}
const T* operator->() const {return baseItem;};
const T& operator*() const {return *baseItem;};
T* operator->() {return baseItem;};
T& operator*() {return *baseItem;};
virtual ~Handle(void)
{
dec_count();
}
private:
T *baseItem;
std::size_t* refCount;
void dec_count()
{
if (-- *refCount == 0 && baseItem != NULL)
{
delete baseItem;
delete refCount;
}
}
};
This is the main function :
int _tmain(int argc, _TCHAR* argv[])
{
BaseItem item1;
ChildItem item2;
vector<Handle<BaseItem> > vec;
vec.push_back(Handle<BaseItem>(item1));
vec.push_back(Handle<BaseItem>(item2));
//for (vector<Handle<BaseItem> >::iterator iter = vec.begin();
// iter != vec.end(); iter++)
//{
//
//}
return 0;
}
when i run the code, the code crashed. i have no idea to debug the code.
This is the error:
Your Handle's copy c-tor is invalid. It should be like this:
Handle(const Handle<T>& other)
: baseItem(other.baseItem),
refCount(other.refCount)
{
++*refCount;
}
http://ideone.com/DB7L9p
The problems I can see are:
The copy constructor should share and increase the reference count, rather than create a new one;
The base class needs a virtual destructor.
The first issue causes a double deletion after copying the handle into the vector. Both copies think they are the only reference to the object and hence both try to delete it. This is probably the cause of the crash.
After fixing those, your code appears to run correctly. If you still have problems, I suggest stepping through your failing test case with a debugger.
Reference count should be a part of actual object rather than part of Handle. Handle should only increment & decrement the reference count & it should create once.
template <typename T>
class RefCounted
{
public:
std::size_t refCount;
};
class BaseItem : public RefCounted<BaseItem> {
So all classes which is being usable with Handle shall be derived from RefCounted.
template <typename T> class Handle
{
public:
Handle():baseItem(NULL) {}
Handle(T& object):baseItem(object.clone())) {++ other.refCount;}
Handle(const Handle<T>& other):baseItem(other.baseItem) { ++ other.refCount; }
Handle& operator= (const Handle<T>& other)
{
++ other.refCount;
baseItem = other.baseItem;
return *this;
}
const T* operator->() const {return baseItem;};
const T& operator*() const {return *baseItem;};
T* operator->() {return baseItem;};
T& operator*() {return *baseItem;};
virtual ~Handle(void)
{
if (baseItem != NULL && -- (baseItem->refCount) == 0)
{
delete baseItem;
}
}
private:
T *baseItem;
};
(Disclaimer: It is not a working code, just attempted to explain the concept)
If you are looking for better implementation, Refer http://trac.webkit.org/browser/trunk/Source/WTF/wtf/RefCounted.h
Related
Edit: I had copied the base template for the statisticscompiler class from another solution, and it seems I somehow had ended up editing the original one while including the new one (that hadn't been edited yet) which is what led to the errors. So a tale of caution against copy pasting code into another file with the same name.
I will just post the header files because I think that's what matters here, let me know if otherwise and I can post the cpp. I have one base class that collects statistics from a process, with two derived classes and then a class that let's me use several statistics classes at once
Statistics.h
#pragma once
#define STATISTIC_H
#include <vector>
#include "Arrays.h"
class Statistics
{
public:
Statistics() {}
virtual void DumpOnePath(MJArray results) = 0;
virtual std::vector<std::vector<double>> GetResultsSoFar() const = 0;
virtual Statistics* clone() const = 0;
virtual ~Statistics() {}
private:
};
class StatisticsMean : public Statistics
{
public:
StatisticsMean();
virtual void DumpOnePath(MJArray results) ;
virtual std::vector<std::vector<double>> GetResultsSoFar() const ;
virtual Statistics* clone() const;
private:
MJArray RunningSums;
unsigned long PathsDone;
};
class StatisticsQuantiles : public Statistics
{
public:
StatisticsQuantiles(double p_lower_, double p_upper_);
virtual void DumpOnePath(MJArray results);
virtual std::vector<std::vector<double>> GetResultsSoFar() const;
virtual Statistics* clone() const;
private:
std::vector<MJArray> RunningResults;
unsigned long PathsDone;
double p_lower;
double p_upper;
};
StatisticsCompiler.h
#pragma once
#define STATISTICS_COMPILER_H
#include "statistics.h"
#include "wrapper.h"
class StatisticsCompiler : public Statistics
{
public:
StatisticsCompiler(const std::vector <Wrapper<Statistics>>& Inner_);
virtual Statistics* clone() const;
virtual void DumpOnePath(MJArray results);
virtual std::vector<std::vector<double>> GetResultsSoFar() const;
private:
std::vector <Wrapper<Statistics>> Inner;
};
And in my main class I'm trying to do this:
StatisticsMean meanGatherer;
StatisticsQuantiles quantileGatherer(p_lower, p_upper);
vector<Wrapper<Statistics>> gathererArray{ meanGatherer, quantileGatherer};
StatisticsCompiler meanAndQuantileGatherer(gathererArray);
Which gives an error no the last line complaining that "No instance of constructor matches the argument list. Argument types are:
(std::vector<Wrapper<Statistics>, std::allocator<Wrapper<Statistics>>>)."
But isn't that exactly what I've defined the constructor to accept? at least the first part, I don't know what
std::allocator<Wrapper<Statistics>>
means.
Wrapper.h in case needed. It does the memory handling
#pragma once
#define WRAPPER_H
template< class T>
class Wrapper
{
public:
Wrapper()
{
DataPtr = 0;
}
Wrapper(const T& inner)
{
DataPtr = inner.clone();
}
~Wrapper()
{
if (DataPtr != 0)
delete DataPtr;
}
Wrapper(const Wrapper<T>& original)
{
if (original.DataPtr != 0)
DataPtr = original.DataPtr->clone();
else
DataPtr = 0;
}
Wrapper& operator=(const Wrapper<T>& original)
{
if (this != &original)
{
if (DataPtr != 0) {
delete DataPtr;
}
DataPtr = (original.DataPtr != 0) ? original.DataPtr->clone() : 0;
}
return *this;
}
T& operator*()
{
return *DataPtr;
}
const T& operator*() const
{
return *DataPtr;
}
const T* const operator->() const
{
return DataPtr;
}
T* operator->()
{
return DataPtr;
}
private:
T* DataPtr;
};
I have a World class and a Entity class.
The World class creates new Entites and retuns a pointer to it.
If i use that pointer im never sure if that pointer is still pointing to a valid Entity but i also dont want to use a shared_ptr because the Entity wont get deleted until all shared_ptr are released. So after some time i cameup with this pointer:
#include <iostream>
#include <unordered_map>
template<class T>
class Pointer
{
public:
Pointer() :m_ptr(nullptr){}
Pointer(T*p) :m_ptr(p) { m_ptr->addPtr(this); }
~Pointer() { if(valid()) m_ptr->removePtr(this); }
Pointer(const Pointer &other) :m_ptr(other.m_ptr)
{
if(valid())
m_ptr->addPtr(this);
}
Pointer& operator=(const Pointer& other)
{
if (valid())
m_ptr->removePtr(this);
m_ptr = other.m_pObj;
if (valid())
m_ptr->addPtr(this);
return *this;
}
T* operator->() { return m_ptr; }
T* operator*() { return *m_ptr; }
T* get() { return m_ptr; }
bool valid() { return m_ptr != nullptr; }
private:
template<typename T>
friend class PointerCollector;
T * m_ptr;
};
template <class T>
class PointerCollector
{
public:
PointerCollector() = default;
virtual ~PointerCollector()
{
for (auto &x : m_ptrList)
{
(x.second)->m_ptr = nullptr;
}
}
private:
void addPtr(Pointer<T> *ptr)
{
m_ptrList[ptr] = ptr;
}
void removePtr(Pointer<T> *ptr)
{
m_ptrList.erase(ptr);
}
template<typename T>
friend class Pointer;
std::unordered_map<Pointer<T>*, Pointer<T>*> m_ptrList;
};
class Test : public PointerCollector<Test>
{
public:
Test() {}
~Test() = default;
int getVal() { return m_val; }
private:
int m_val = 100;
};
void func(Pointer<Test> ptr)
{
if (ptr.valid())
{
std::cout << ptr->getVal();
}
else
{
std::cout << "Invalid!\n";
}
}
int main()
{
Test* myTest = new Test();
Pointer<Test> myPtr(myTest);
Pointer<Test> myPtr2(myPtr);
delete myTest;
func(myPtr2);
getchar();
return 0;
}
the Test class will collect the pointers to it and invalidates them if the class gets deleted.
Now i wanted to ask if anyone knows a better implementation or more infomation about this kind of pointer.
I compiled and tested the above code in Visual Studio 2017
The answer is yes, this pattern has been used before by many people. You just created a poor (and broken, because there's at least one outright bug and several things that are sub-optimal) re-implementation of ::std::weak_ptr<T>. You should consider using it instead.
I am building an add-in for a program. My add-in manipulates Ptr objects passed to me by the host application. I would like to create a vector of externally created and managed objects by the host. Unfortunately, the documentation doesn't have any clear examples of how to do this.
class Players {
vector<Ptr<Player>> vectorOfGamers; // who deletes and when this?
public void CreatePlayers () {
// call static application to create three players
for ( int i = 0; i < 3; i++ )
vectorOfGamers.push_back(Application.GetNextPlayer());
}
}
Confused about how to build this class and prevent memory leaks and causing a null exception if items are deleted prematurely. Also, how do I use modern C++ facilities to achieve this yet gain as much of the benefits of the new memory management like make_shared, make_unique, nullptr, etc?
For your information, below is a snapshot of Ptr.I am confused about the Ptr as it appears superfluous given modern C++'s new memory management facilities.
class IncompleteType
{
public:
template<typename T> static void addref(void* ptr) { reinterpret_cast<adsk::core::ReferenceCounted*>(ptr)->addref(); }
template<typename T> static void release(void* ptr) { reinterpret_cast<adsk::core::ReferenceCounted*>(ptr)->release(); }
};
class CompleteType
{
public:
template<typename T> static void addref(T* ptr) { ptr->addref(); }
template<typename T> static void release(T* ptr) { ptr->release(); }
};
template<class T, class PT = IncompleteType>
class Ptr
{
public:
typedef T element_type;
Ptr() : ptr_(nullptr) {}
Ptr(const Ptr& rhs) : ptr_(nullptr) { reset(rhs.ptr_); }
Ptr(const T* ptr, bool attach = true) : ptr_(nullptr) { reset(ptr, attach); }
// casting constructor. call operator bool to verify if cast was successful
template<class V, class VPT>
Ptr(const Ptr<V, VPT>& rhs) : ptr_(nullptr) {
if (rhs)
reset(rhs->template query<T>(), false);
}
~Ptr() { reset(nullptr); }
void operator=(const Ptr<T, PT>& rhs) { if (&rhs != this) reset(rhs.ptr_); }
void operator=(const T* ptr) { reset(ptr, true); }
// casting assignment operator. call operator bool to verify if cast was successful
template<class V, class VPT>
void operator=(const Ptr<V, VPT>& rhs) {
if (rhs)
reset(rhs->template query<T>(), false);
else
reset(nullptr);
}
void reset(const T* ptr, bool attach = false) {
if (ptr_ != ptr)
{
if (ptr_)
PT::template release<T>(ptr_);
ptr_ = const_cast<T*>(ptr);
if (!attach && ptr_)
PT::template addref<T>(ptr_);
}
}
T* operator->() const { assert(ptr_ != nullptr); if (ptr_ == nullptr) throw std::exception(); return ptr_; }
// Test if this pointer is empty (if operator-> will throw)
/*explicit*/ operator bool() const { return ptr_ != nullptr; }
bool operator==(const Ptr& rhs) const { return ptr_ == rhs.ptr_; }
bool operator!=(const Ptr& rhs) const { return ptr_ != rhs.ptr_; }
bool operator<(const Ptr& rhs) const { return ptr_ < rhs.ptr_; }
// Iteration support. Only usable if T has count and item members and an iterable_type
typedef Iterator<T, PT> iterator;
iterator begin() const { return Iterator<T, PT>(*this); }
iterator end() const { return Iterator<T, PT>(*this, true); }
// Caution the following functions if used incorrectly can cause a reference count leak
T* get() const { return ptr_; }
T* detach() { T* t = ptr_; ptr_ = nullptr; return t; }
private:
T* ptr_;
};
You’re probably right that Ptr wouldn’t be needed in a post-C++03 environment. Probably your plugin API is old enough that C++11 wasn’t around back then. From the code you posted my best guess is that Ptr is supposed to be a reference counted smart pointer that manages shared ownership like std::shared_ptr does.
How exactly you use that thing should become clear from the plguin API documentation and maybe the source code of your host program. Just from the snippet you posted and without even mentioning the program’s name it’s impossible to say anything definite.
Consider the following class that wraps a container and type-erases its type:
class C final {
struct B {
virtual bool empty() const noexcept = 0;
};
template<class T, class A>
struct D: public B {
// several constructors aimed to
// correctly initialize the underlying container
bool empty() const noexcept override { return v.empty(); }
private:
std::vector<T, A> v;
};
// ...
public:
//...
bool operator==(const C &other) const noexcept {
// ??
// would like to compare the underlying
// container of other.b with the one
// of this->b
}
private:
// initialized somehow
B *b;
};
I'd like to add the operator== to the class C.
Internally, it should simply invoke the same operator on the underlying containers, but I'm stuck on this problem, for I don't know how to do that.
The idea is that two instances of C are equal if the operator== of their underlying containers return true.
Whatever I've tried till now, I ever ended up being unable to get the type of one of the two underlying containers, mainly the one of other.
Is there an easy solution I can't see at the moment or I should give up?
Despite the good suggestion from juanchopanza, I found that, as far as the underlying containers represent the same concept (as an example, different specializations of a vector), maybe there is no need of a type-erased iterator.
Below it's a possible implementation that relies on the operator[] and the size member method:
#include <vector>
#include <cassert>
class Clazz final {
struct BaseContainer {
virtual std::size_t size() const noexcept = 0;
virtual int operator[](std::size_t) const = 0;
virtual void push_back(int) = 0;
};
template<class Allocator>
struct Container: public BaseContainer {
Container(Allocator alloc): v{alloc} { }
std::size_t size() const noexcept override { return v.size(); }
int operator[](std::size_t pos) const override { return v[pos]; }
void push_back(int e) override { v.push_back(e); }
private:
std::vector<int, Allocator> v;
};
public:
template<class Allocator = std::allocator<int>>
Clazz(const Allocator &alloc = Allocator{})
: container{new Container<Allocator>{alloc}} { }
~Clazz() { delete container; }
void push_back(int e) { container->push_back(e); }
bool operator==(const Clazz &other) const noexcept {
const BaseContainer &cont = *container;
const BaseContainer &oCont = *(other.container);
bool ret = (cont.size() == oCont.size());
for(std::vector<int>::size_type i = 0, s = cont.size(); i < s && ret; i++) {
ret = (cont[i] == oCont[i]);
}
return ret;
}
bool operator!=(const Clazz &other) const noexcept {
return !(*this == other);
}
private:
BaseContainer *container;
};
int main() {
Clazz c1{}, c2{}, c3{};
c1.push_back(42);
c2.push_back(42);
assert(c1 == c2);
assert(c1 != c3);
}
Open to criticism, hoping this answer can help other users. :-)
Assuming you wish to return false when the comparing two different containers, this should do the job (caution: untested):
class Container
{
struct Concept
{
virtual ~Concept() = default;
virtual Concept* clone() const = 0;
virtual bool equals(Concept const*) const = 0;
};
template<typename T>
struct Model final : Concept
{
Model(T t) : data{std::move(t)} {}
Model* clone() const override { return new Model{*this}; }
virtual bool equals(Concept const* rhs) const override
{
if (typeid(*this) != typeid(*rhs))
return false;
return data == static_cast<Model const*>(rhs)->data;
}
T data;
};
std::unique_ptr<Concept> object;
public:
template<typename T>
Container(T t) : object(new Model<T>{std::move(t)}) {}
Container(Container const& that) : object{that.object->clone()} {}
Container(Container&& that) = default;
Container& operator=(Container that)
{ object = std::move(that.object); return *this; }
friend bool operator==(Container const& lhs, Container const& rhs)
{ return lhs.object->equals(rhs.object.get()); }
};
I need to create a generic object carrier class. I came up with something simple like
template<typename T>
class ObjectCarrier
{
public:
const T& item() const
{
return item_;
}
void setItem(T& item)
{
item_ = item;
}
private:
T item_;
};
This works well when T has got a default constructor (parameterless). Things gets complicated when T has parameterized constructors. So I rewrote the class like
template<typename T>
class ObjectCarrier
{
public:
const T& item() const
{
return *item_;
}
void setItem(T& item)
{
item_ = new T ( item );
}
private:
T* item_;
};
Changed the item_ variable to T* and created a new instance using the copy constructor of T. Again this worked well until T is a pointer type. I mean ObjectCarrier<Foo*> won't work.
I am wondering how can I design this class so that it works for almost all kind of types. I think I may need to create a traits type specialized for pointers. But unfortunately, I am not able to make that work.
Any help would be great.
The above approaches are way way too complicated. Keep it simple, and just solve the constructor arg problem by using template constructors. Don't use pointers, they will create object lifetime and copying headaches.
Here's an implementation I use a lot. The template constructors will forward arguments for things directly on to the nested object which is convenient. The operator T& values let you pass carrier<T> to functions that take a type T, without expensive copying. You can wrap objects that take up to two arguments with this code.
/* A wrapper of type T */
template <typename T>
struct carrier {
carrier() {}
template <typename A1> carrier(const A1& a1) : value(a1) {}
template <typename A1, typename A2> carrier(const A1& a1, const A2& a2) : value(a1, a2) {}
operator T&() { return value; }
operator const T&() const { return value; }
T value;
};
You can use it like this:
const carrier<point> p1(10,10); // make p1 const to stop people changing it
showPoint(p1); // calls a function that expects a point,
showPoint(p1.value); // access the point directly
You can use template specialization for the T* type and rewrite the methods to suite pointers. You can do something like:
template<typename T>
class ObjectCarrier<T*>
{
public:
const T* item() const
{
return item_;
}
void setItem(T* item)
{
item_ = item;
}
private:
T* item_;
};
There is a design patern that is possibly relevant to this - Memento.
A bit off topic, but bear in mind that as soon as you start newing objects up inside your class, you'll need a way to manage the memory. I'd suggest using an std::auto_ptr at the least. You'll also need to provide a copy constructor and an assignment operator, when using std::auto_ptr.
It might be possible to hold the object by value and still defer its construction with the use of placement new and something like the following:
#include <iostream>
#include <cassert>
template <class T>
class ObjectCarrier
{
public:
ObjectCarrier(): ref(0) {}
ObjectCarrier(const ObjectCarrier& other): ref(0)
{
set_data(other.ref);
}
~ObjectCarrier()
{
clear();
}
const ObjectCarrier& operator = (const ObjectCarrier& other)
{
if (other.empty())
clear();
else
set_data(other.ref);
return *this;
}
void set(const T& value)
{
set_value(value);
}
const T& get() const
{
assert(!empty() && "No object being carried");
return *ref;
}
bool empty() const
{
return ref == 0;
}
void clear()
{
if (!empty()) {
ref->~T();
ref = 0;
}
}
private:
char data[sizeof(T)];
T* ref;
void set_value(const T& value)
{
if (!empty()) {
*ref = value;
}
else {
ref = new (data) T(value);
}
}
void set_data(const T* value)
{
if (value) {
set_value(*value);
}
}
};
int main()
{
ObjectCarrier<int> i;
ObjectCarrier<int> j(i);
i = j;
i.set(10);
std::cout << i.get() << '\n';
j = i;
i.set(20);
std::cout << i.get() << ' ' << j.get() << ' ' << ObjectCarrier<int>(i).get() << '\n';
}
However, I would somewhat question the usefulness of this class. Perhaps the only purpose it could have, would be to act as Boost.Optional.
But if you don't want the class to be able to not hold a value, just give it a parametrized constructor:
template<typename T>
class ObjectCarrier
{
public:
ObjectCarrier(const T& value = T()):
item_(value)
{
}
const T& item() const
{
return item_;
}
void setItem(T& item)
{
item_ = item;
}
private:
T item_;
};
(It's just that this class seems rather useless, unless perhaps as a facade for code that expects variables to have item and setItem methods, rather than, say, an assignment operator.)
boost::optional does something very similar to this (also boost::any, but nevermind).
You can check out how its implemented at: http://cplusplus.co.il/2009/12/04/boost-optional-and-its-internals/ and don't worry - it's pretty straightforward.