Output cout is exclamation mark. C++ - c++

I've been told to write header file to the main.cpp which contains this:
OOP::array tab;
for(int i = 0; i < rand()%10 + 1; ++i)
{
tab.push_back(new BaseClass("BaseClass 1"));
tab.push_back(new BaseClass("BaseClass 2"));
tab.push_back(new BaseClass("BaseClass 3"));
}
OOP::print_tab_el(tab); //prints tab using operator<< for its elements.
Class array is a container for smart pointers.
So I implemented counted_ptr, BaseClass and array (I used std::vector as a container) classes but when I invoke "print_tab_el(tab)" function, I get exclamation mark!
Seems like all of vector's items which are smart pointers contain "!" as name. I never put an "!" there.
Here's my header.
namespace OOP {
class BaseClass
{
public:
std::string name;
BaseClass(std::string arg) {name=arg;}
friend std::ostream & operator<<(std::ostream &os, const BaseClass& ref)
{
os<<ref.name<<"\n"; //gives ! ???
return os;
}
};
class array
{
public:
std::vector <counted_ptr<OOP::BaseClass> > myvec;
void push_back( OOP::BaseClass *arg)
{
counted_ptr< OOP::BaseClass> tmp(arg);
myvec.push_back(tmp);
}
};
void print_tab_el(array arr)
{
std::vector <counted_ptr<OOP::BaseClass> >::iterator it;
for (it=arr.myvec.begin();it!=arr.myvec.end();++it){
std::cout<<**it;
}
}
};
And this is program output:
!
!
!
!
!
!
!
!
and some more.
ADDED:
counted_ptr.cpp
#ifndef COUNTED_PTR_CPP
#define COUNTED_PTR_CPP
#include "counted_ptr.h"
#include <iostream>
/****************************************************************************/
template <class T>
counted_ptr<T>::counted_ptr(T* pointer):ptr(pointer)
{
refs.addRef();
}
/****************************************************************************/
template <class T>
counted_ptr<T>::counted_ptr(const counted_ptr& ref):ptr(ref.ptr), refs(ref.refs+1) {}
/****************************************************************************/
template <class T>
counted_ptr<T>::~counted_ptr()
{
if (refs.takeRef()==0)
delete ptr;
}
/****************************************************************************/
template <class T>
T* counted_ptr<T>::operator->(){
return ptr;
}
/****************************************************************************/
template <class T>
T& counted_ptr<T>::operator*(){
return *ptr;
}
/****************************************************************************/
template <class T>
counted_ptr<T>& counted_ptr<T>::operator=(const counted_ptr<T>& rcpt_r){
if (this!=&rcpt_r)
{
if (refs.takeRef()==0)
delete ptr;
ptr=rcpt_r.ptr;
//refs=rcpt_r.refs+1;
refs=rcpt_r.refs;
refs.addRef();
}
return *this;
}
/****************************************************************************/
#endif
counted_ptr.h
#ifndef COUNTED_PTR_H
#define COUNTED_PTR_H
#include "reference.h"
template <class T>
class counted_ptr{
public:
counted_ptr( T* pointer);
counted_ptr(const counted_ptr& ref);
~counted_ptr();
T* operator->();
T& operator*();
counted_ptr& operator=(const counted_ptr<T>& ref);
private:
T *ptr;
reference refs;
};
class testclass{};
#endif
#include "counted_ptr.cpp"
reference.cpp
#include "reference.h"
#include <iostream>
/****************************************************************************/
reference::reference():nr_of_references(0){}
/****************************************************************************/
reference::reference(const int value):nr_of_references(value){}
reference& reference::operator=(const int& ref)
{
nr_of_references=ref;
return *this;
}
/****************************************************************************/
reference::operator int()const
{
return nr_of_references;
}
/****************************************************************************/
int reference::addRef()
{
return ++nr_of_references;
}
/****************************************************************************/
int reference::takeRef()
{
return --nr_of_references;
}
/****************************************************************************/
reference.h
class reference{
public:
reference();
reference(const int value);
//reference& operator=(const reference& ref);
reference& operator=(const int& ref);
operator int()const;
int addRef();
int takeRef();
private:
int nr_of_references;
};

Every instance of counted_ptr has its own instance of reference. Each instance of reference has its own instance of nr_of_references. Although each counter_ptr manages reference properly, the problem is that the counted_ptr that only had a count of 1 will destruct the pointer when it goes out of scope, even after it was copied to a different counted_ptr instance.
Your counted_ptr needs to be redesigned so that all counted_ptrs to the same object also manipulate the same reference.

Related

C++ override member access operator for template class and return by reference

Is it possible to override the -> operator in template class and return something by reference?
I saw this post: Overloading member access operators ->, .*
And there is an example of overriding -> and return by reference, but I can't get this to work with templates. Here's a small example of what I'm trying to achieve:
#include <iostream>
using namespace std;
class A
{
public:
void do_something()
{
cout << "Hey there";
}
};
template<class T>
class Ref
{
public:
Ref(T* ptr)
{
objPtr = ptr;
}
// this is another alternative, but I don't want to write Get() every time I want to access the object
T& get() { return *objPtr; }
template <class T>
Ref<T>& operator->() const { return *objPtr; }
// doesn't work either
//T& operator->() const { return *objPtr; }
// this works as expected, but I really MUST return by reference
//T* operator->() const { return objPtr; }
private:
T* objPtr;
};
int main()
{
A myObj;
Ref<A> ref(&myObj);
// error C2675: unary '->': 'Ref<A>' does not define this operator or a conversion to a type acceptable to the predefined operator
ref->do_something();
return 0;
}
How can this be done?
If you return a reference, you can't use it in ref->do_something(); which requires a pointer. You'd have to use this cumbersome method:
ref.operator->().do_something();
Instead return a pointer - and make it a T* (or const T*), not a Ref<T>*.
Example:
#include <iostream>
class A {
public:
void do_something() {
std::cout << "Hey there\n";
}
};
template<class T>
class Ref {
public:
Ref(T& ptr) : objPtr(&ptr) {} // taking a T& but storing a pointer
const T* operator->() const { return objPtr; }
T* operator->() { return objPtr; }
private:
T* objPtr;
};
int main() {
A myObj;
Ref<A> ref(myObj);
ref->do_something();
}

Pointer chain broken when overloading operators

Got this code (should be all that is relevant):
//movable_ptr.hpp
//Michal Cermak
#ifndef MOVABLE_H
#define MOVABLE_H
template<typename T> class movable_ptr;
template<typename T> class enable_movable_ptr {
public:
//default constructor
enable_movable_ptr() {};
enable_movable_ptr(T* p) : ptr_(p) {};
//operators...
T& operator*() const { return *ptr_; };
T* operator->() const { return ptr_; };
bool operator==(const enable_movable_ptr<T>& p) const { return p.ptr_ == ptr_; };
T* get() {return ptr_; };
private:
T* ptr_ = nullptr;
};
template<typename T> class movable_ptr {
public:
//parameterless constructor
movable_ptr() {};
//constructor from T*
movable_ptr(T* p) : ptr_(p) { add_to_tracked(this); };
//operators ...
enable_movable_ptr<T>& operator*() const { return *ptr_; };
enable_movable_ptr<T>* operator->() const { return ptr_; };
bool operator==(const movable_ptr<T>& p) const { return p.ptr_ == ptr_; };
//access to variables
enable_movable_ptr<T>* get() {return ptr_; };
void set(enable_movable_ptr<T>* p) { ptr_ = p; };
private:
enable_movable_ptr<T>* ptr_ = nullptr;
};
template<typename T> movable_ptr<T> get_movable(enable_movable_ptr<T>& p){
return new movable_ptr<T>(p);
};
#endif
My problem is that when I run the following code (or other similar ones for that matter), the movable_ptr<T> doesn't get de-referenced all the way to A, but gets stuck on enable_movable_ptr<A>, which causes comparisons and other stuff to throw errors, because "'val' is not a member of enable_movable_ptr<A>". It is a member of A though, so if I de-reference correctly, it should then work.
#include <iostream>
#include <memory>
#include <string>
#include "movable_ptr.hpp"
using namespace std;
class A : public enable_movable_ptr<A>
{
public:
int val;
A(int val) : val(val) {}
};
void test_ptr_dereference() {
A x(42);
auto px = get_movable(x);
TEST_ASSERT(&*px == &x);
TEST_ASSERT(&px->val == &x.val);
}
int main(int argc, char* argv[]) {
test_ptr_dereference();
}
I am guessing I did something wrong in the overloaded operators, but otherwise have no clue. Any ideas on how to fix it?

C++ segmentation fault when I have an Array inside an Array

I tried to implement my own class named Array that act mostly like a vector because I don't want to use std. It works well with basic classes but when I want to instantiate an Array of a class that contains an Array (class Scene for exemple) it stops the program saying "Windows stoped fonctionning"... When I try to search for the error with break points I saw that it says "segmentation fault" when the program is at the destructor.
Here's my classes :
Array.h
#ifndef NAME_ARRAY_H
#define NAME_ARRAY_H
#include <stdexcept>
#include <iostream>
#include "malloc.h"
template <class T>
class Array {
private:
T *m_array;
unsigned int m_tot_size;
unsigned int m_actual_size;
public:
Array(unsigned int size);
Array(Array<T> const& paste);
bool add(T var);
const T& get(unsigned int index);
bool remove(unsigned int index);
void kill();
unsigned int getActualSize() const;
unsigned int getTotalSize() const;
T* getArray() const;
T& operator[](unsigned int index);
Array<T>& operator=(Array<T> const& paste);
~Array();
};
//CONSTRUCTOR
template <class T>
Array<T>::Array(unsigned int size) : m_tot_size(size), m_actual_size(0) {
m_array = (T*) malloc(size * sizeof(T));
}
template <class T>
Array<T>::Array(Array<T> const &paste) : m_tot_size(paste.m_tot_size),
m_actual_size(paste.m_actual_size) {
m_array = new T(*(paste.m_array));
}
//METHODES PUBLIC
template <class T>
const T & Array<T>::get(unsigned int index) {
if (index >= m_actual_size || index < 0)
throw std::out_of_range("Index out of range");
return m_array[index];
}
template <class T>
bool Array<T>::remove(unsigned int index) {
if(index < m_actual_size && m_actual_size != 0) {
m_actual_size--;
m_array[index] = m_array[m_actual_size];
return true;
}
return false;
}
template <class T>
bool Array<T>::add(T obj) {
if (m_actual_size >= m_tot_size) {
T *temp;
temp = (T*) realloc(m_array,5*sizeof(T));
m_array = temp;
m_array[m_actual_size] = obj;
m_actual_size++;
m_tot_size += 5;
return false;
} else {
m_array[m_actual_size] = obj;
m_actual_size++;
return true;
}
}
template <class T>
void Array<T>::kill() {
free(m_array);
delete [] m_array;
m_array = nullptr;
m_actual_size = 0;
m_tot_size = 0;
}
//ACCESSOR
template <class T>
unsigned int Array<T>::getActualSize() const { return m_actual_size; }
template <class T>
unsigned int Array<T>::getTotalSize() const { return m_tot_size; }
template <class T>
T* Array<T>::getArray() const { return m_array; }
//OPERATOR
template <class T>
T& Array<T>::operator[](unsigned int index) { return m_array[index]; }
template <class T>
Array<T>& Array<T>::operator=(Array<T> const& paste) {
if(this != &paste) {
m_tot_size = paste.m_tot_size;
m_actual_size = paste.m_actual_size;
free(m_array);
delete [] m_array;
m_array = nullptr;
m_array = new T(*(paste.m_array));
}
return *this;
}
//DESTRUCTOR
template <class T>
Array<T>::~Array() {
free(m_array);
delete [] m_array;
m_array = nullptr;
}
Scene.cpp :
#include "Scene.h"
Scene::Scene(std::string sceneName) : m_name(sceneName), m_array_position(20) {
}
void Scene::update() {}
void Scene::render() {}
Scene::~Scene() {
//m_array_position.kill();
//m_array_systems.kill();
}
Scene.h
#ifndef NAME_SCENE_H
#define NAME_SCENE_H
#include <string>
#include <unordered_map>
#include "../components/Position.h"
#include "../utils/Array.h"
#include "../systems/System.h"
class Scene {
private:
std::string m_name;
Array<Position> m_array_position;
public:
Scene(std::string sceneName);
void update();
void render();
~Scene();
};
main
Array<Scene> scenes(1);
I think the problem is that the program destroy the Array and then try to destroy the Array (Position is just a struct) but I'm not sure and I don't know what to do to correct it. Can someone please help me ?
I see in a lot of places code like this:
free(m_array);
delete [] m_array;
This doesn't look good to me. When allocating and deallocating memory, you have to match the allocation method with the deallocation:
If you reserve memory with "malloc", you free it with "free"
If you reserve with "new", you deallocate with "delete"
If you reserve with "new []", then you free with "delete []"
You should only use one of the methods or, if you REALLY need to mix them, then you should keep something tracking which method you would need to free the memory.

error: 'template<class T> class Dynamic_Array' used without template parameters

I've been getting this error for some time, and I have no clue how to fix it.
I searched for similar problem here on stack overflow, but I've failed to find anything.
Source code:
template <typename T>
class Dynamic_Array
{
private:
T* actual_array;
unsigned int number_of_elements;
public:
Dynamic_Array() {}
~Dynamic_Array() {delete[] actual_array;}
unsigned int get_size() const {return number_of_elements;}
T& operator [](unsigned int index) {return actual_array[index];}
void operator +=(T&);
void operator -=(unsigned int);
};
template <typename T> /*Not sure if this is needed, but compiler doesn't mind, still prints the same error*/
void Dynamic_Array<T>::operator+=(T& object)
{
if(number_of_elements>1)
{
T* temp_array = new T[number_of_elements];
for(unsigned int i=0;i<number_of_elements;i++)
{
temp_array[i]=actual_array[i];
}
delete[] actual_array;
actual_array = new T[number_of_elements+1];
for(unsigned int i=0;i<number_of_elements;i++)
{
actual_array[i]=temp_array[i];
}
delete [] temp_array;
temp_array=NULL;
actual_array[number_of_elements]=object;
number_of_elements++;
}
else
{
number_of_elements++;
actual_array = new T[1];
}
}
void Dynamic_Array<T>::operator-=(unsigned int index)
{
T* temp_array = new T[number_of_elements-1];
for(unsigned int i=0, j=0;i<number_of_elements;i++)
{
if(i!=index)
{
temp_array[j]=actual_array[i];
j++;
}
}
delete[] actual_array;
number_of_elements--;
actual_array = new T[number_of_elements];
for(unsigned int i=0;i<number_of_elements;i++)
{
actual_array[i]=temp_array[i];
}
delete [] temp_array;
temp_array = NULL;
}
According to compiler, the error is present in line 18 (the empty one between "};" and "template"
As I said, I have no idea what I screwed up, so any help is appreciated.
When you define member functions outside of a class template declaration then you need to specify the template for each function. When you define
void Dynamic_Array<T>::operator-=(unsigned int index)
{
//...
}
You need to have the template part as well like
template <typename T>
void Dynamic_Array<T>::operator-=(unsigned int index)
{
//...
}
This has to be present for every function definition that you do out of line. A single template <typename T> at the start of all the definition does not apply to all of the function definitions.
Dynamic_Array is a template class so when defining operator+= and operator-= outside the scope of the class you need to provide template type as follows:
template<typename T> void Dynamic_Array<T>::operator+=(T& object) {
//...
}
template<typename T> void Dynamic_Array<T>::operator-=(unsigned int index) {
//...
}
Also, I should note that it is somewhat odd to have void as a return type for operator+= and operator-=, typically you should return a reference to the altered instance of this, i.e:
template<typename T> Dynamic_Array<T>& Dynamic_Array<T>::operator+=(const T& object) {
//...
}

C++ function pointer in constructor

I am trying to pass a function pointer in to a constructor of a class. However, when I try to compile the code, I am getting an error. The code and error are :
quickfind.h
#ifndef QUICKFIND_H
#define QUICKFIND_H
#endif // QUICKFIND_H
template <class T>
class QuickFind
{
private:
int size;
int *array;
int (*giveIndex)(const void *a);
public:
QuickFind<T>(int n,int (*ptr)(const void *));
void connect (const T* u,const T* v);
bool isConnected(const T* u,const T* v);
};
Constructor definition in file quickfind.cpp
template <class T>
QuickFind<T>::QuickFind(int n,int (*ptr)(const void *))
{
size=n;
array=new int[n];
giveIndex=ptr;
for(int i=0;i<n;i++)
{
array[i]=i;
}
}
In my main function file :
int giveIndex (const void *ptr)
{
temp *tptr=(temp*)ptr;
return tptr->getA();
}
int main()
{
QuickFind<temp> *qf=new QuickFind<temp>(10,giveIndex);
}
Here, I am getting 'undefined reference to QuickFind<temp>::QuickFind(int, int (*)(void const*))' error. I am not able to figure out the problem...please help.
One thing wrong, you don't need the on the constructor:
template <class T>
class QuickFind
{
private:
int size;
int *array;
int (*giveIndex)(const void *a);
public:
QuickFind(int n,int (*ptr)(const void *)); /// <---- here, no <T>
void connect (const T* u,const T* v);
bool isConnected(const T* u,const T* v);
};
In your case, the class it templated, but this function isn't. And, template functions must be defined in the header file so that the file that includes them can see the code and substitute the parameter types.
Put all of the following in one CPP file to see it work. As noted in other comments you must, for templated classes, put the entire definition in the header file. Do not separate the function declaration from its definitions into a separate CPP file. In this case having the entire implementation in the one CPP file serves the same purpose.
I have made some changes to your code to make it typesafe, memory leak safe and more exception safe. For example I replaced your dynamically allocated array with std::vector. std::vector has all the features you need but manages the memory for you and will be cleaned up when your class goes out of scope.
#include <vector>
#include <iostream>
#include <functional>
template <typename T>
class QuickFind
{
private:
std::vector<int> data;
std::function<int (const T&)> func;
public:
QuickFind(int n, std::function<int (const T&)> f) : data(n), func(f)
{
int i = 0;
for(auto it = data.begin(); it != data.end(); ++it)
data[i]=i++;
}
void connect (const T& u, const T& v)
{
std::cout << func(u) << "\n";
std::cout << func(v) << "\n";
}
bool isConnected(const T* u,const T* v);
};
class temp
{
int val;
public:
temp(int i) : val(i)
{}
int getA() const
{
return val;
}
};
int giveIndex (const temp &t)
{
return t.getA();
}
int main()
{
temp t1(5), t2(10);
QuickFind<temp> qf1(10,giveIndex);
qf1.connect(t1, t2);
// this example uses a lambda as the callback
auto giveIndex2 = [](const temp& t) { return t.getA(); };
QuickFind<temp> qf2(20, giveIndex2);
qf2.connect(t1, t2);
}
The compiler wants to know objects of which types will be instantiated from a template class at the time of compilation of template class methods. So, there may arise compile-time or link-time errors.
This explains more about various errors and their causes.
Adding #include "quickfind.cpp" in the end of the header file worked in my case after some efforts.