G
Gonçalo Rodrigues
Hi all,
The following (test) program is not working as I expected.
Note: The code is a bit long but is easy to understand: There is a
class Object implementing ref counting. A Ref<T> template (with a full
Ref<Object> specialization) that works like a smart pointer to the
Object-rooted hierarchy. The only way to create Object instances is
via a static factory that returns a Ref<Object> to a heap allocated
object.
#include <iostream>
//Macros.
#ifndef NULL
#define NULL 0
#endif
//Templates.
template<typename T>
class Ref {
public:
//Constructors.
explicit Ref(T* ptr) {
if (NULL == ptr) {
throw "NULL pointer.";
};
this->ptr = ptr;
ptr->incCount();
};
Ref(const Ref& ref) : ptr(ref.getPtr()) {
this->ptr->incCount();
};
//Destructor.
~Ref() {
this->ptr->decCount();
if (0 == this->ptr->getCount()) {
delete this->ptr;
};
this->ptr = NULL;
};
//Descriptors.
T* getPtr() const {
return this->ptr;
};
//Operator protocol.
T& operator*() const {
return *(this->ptr);
}
T* operator->() const {
return this->ptr;
};
private:
T* ptr;
};
//Forward declaration.
class Object;
//Full specialization.
template<>
class Ref<Object> {
public:
//Constructors.
explicit Ref(Object* ptr) {
if (NULL == ptr) {
throw "NULL pointer.";
};
this->ptr = ptr;
ptr->incCount();
};
Ref(const Ref& ref) : ptr(ref.getPtr()) {
this->ptr->incCount();
};
//Destructor.
~Ref() {
this->ptr->decCount();
if (0 == this->ptr->getCount()) {
delete this->ptr;
};
this->ptr = NULL;
};
//Descriptors.
Object* getPtr() const {
return this->ptr;
};
//Operator protocol.
Object& operator*() const {
return *(this->ptr);
}
Object* operator->() const {
return this->ptr;
};
private:
Object* ptr;
};
class Object {
public:
static Ref<Object> create() {
return Ref<Object>(new Object);
};
virtual ~Object() {};
//Reference count helpers.
long getCount() {
return this->count;
};
void incCount() {
this->count++;
};
void decCount() {
this->count--;
};
protected:
//Protect constructors.
Object() : count(0) {};
private:
long count;
//Disallow.
Object(const Object& obj);
Object& operator=(const Object& rhs);
};
int main() {
Ref<Object> ref = Object::create();
std::cout << "Object count: " << ref->getCount() << std::endl;
std::cout << "Object pointer: " << (long)ref.getPtr() <<
std::endl;
Ref<Object> ref1(ref);
std::cout << "Object count: " << ref1->getCount() <<
std::endl;
std::cout << "Object pointer: " << (long)ref1.getPtr() <<
std::endl;
};
Compiling and running is fine and dandy. I get:
Object count: 1
Object pointer: 3082872
Object count: 2
Object pointer: 3082872
But once I replace the copy-constructor in the full specialization
Ref<Object> by the template method
template<typename U>
Ref(const Ref<U>& ref) : ptr(ref.getPtr()) { //Upcast here.
this->ptr->incCount();
};
I get the output
Object count: 1
Object pointer: 3082872
Object count: 1
Object pointer: 3082872
The reference counter is not being updated - although the pointer is
getting assigned. Anyone knows what is wrong with the above template
method? Any ideas?
TIA, best regards,
G. Rodrigues
The following (test) program is not working as I expected.
Note: The code is a bit long but is easy to understand: There is a
class Object implementing ref counting. A Ref<T> template (with a full
Ref<Object> specialization) that works like a smart pointer to the
Object-rooted hierarchy. The only way to create Object instances is
via a static factory that returns a Ref<Object> to a heap allocated
object.
#include <iostream>
//Macros.
#ifndef NULL
#define NULL 0
#endif
//Templates.
template<typename T>
class Ref {
public:
//Constructors.
explicit Ref(T* ptr) {
if (NULL == ptr) {
throw "NULL pointer.";
};
this->ptr = ptr;
ptr->incCount();
};
Ref(const Ref& ref) : ptr(ref.getPtr()) {
this->ptr->incCount();
};
//Destructor.
~Ref() {
this->ptr->decCount();
if (0 == this->ptr->getCount()) {
delete this->ptr;
};
this->ptr = NULL;
};
//Descriptors.
T* getPtr() const {
return this->ptr;
};
//Operator protocol.
T& operator*() const {
return *(this->ptr);
}
T* operator->() const {
return this->ptr;
};
private:
T* ptr;
};
//Forward declaration.
class Object;
//Full specialization.
template<>
class Ref<Object> {
public:
//Constructors.
explicit Ref(Object* ptr) {
if (NULL == ptr) {
throw "NULL pointer.";
};
this->ptr = ptr;
ptr->incCount();
};
Ref(const Ref& ref) : ptr(ref.getPtr()) {
this->ptr->incCount();
};
//Destructor.
~Ref() {
this->ptr->decCount();
if (0 == this->ptr->getCount()) {
delete this->ptr;
};
this->ptr = NULL;
};
//Descriptors.
Object* getPtr() const {
return this->ptr;
};
//Operator protocol.
Object& operator*() const {
return *(this->ptr);
}
Object* operator->() const {
return this->ptr;
};
private:
Object* ptr;
};
class Object {
public:
static Ref<Object> create() {
return Ref<Object>(new Object);
};
virtual ~Object() {};
//Reference count helpers.
long getCount() {
return this->count;
};
void incCount() {
this->count++;
};
void decCount() {
this->count--;
};
protected:
//Protect constructors.
Object() : count(0) {};
private:
long count;
//Disallow.
Object(const Object& obj);
Object& operator=(const Object& rhs);
};
int main() {
Ref<Object> ref = Object::create();
std::cout << "Object count: " << ref->getCount() << std::endl;
std::cout << "Object pointer: " << (long)ref.getPtr() <<
std::endl;
Ref<Object> ref1(ref);
std::cout << "Object count: " << ref1->getCount() <<
std::endl;
std::cout << "Object pointer: " << (long)ref1.getPtr() <<
std::endl;
};
Compiling and running is fine and dandy. I get:
Object count: 1
Object pointer: 3082872
Object count: 2
Object pointer: 3082872
But once I replace the copy-constructor in the full specialization
Ref<Object> by the template method
template<typename U>
Ref(const Ref<U>& ref) : ptr(ref.getPtr()) { //Upcast here.
this->ptr->incCount();
};
I get the output
Object count: 1
Object pointer: 3082872
Object count: 1
Object pointer: 3082872
The reference counter is not being updated - although the pointer is
getting assigned. Anyone knows what is wrong with the above template
method? Any ideas?
TIA, best regards,
G. Rodrigues