I got a template class Atlas that will store objects of Animal class and derived classes of Animal;
here's the code:
#include <iostream>
#include <assert.h>
#include <list>
using namespace std;
class Animal {
protected:
std::string m_name;
Animal (std::string name): m_name {name} {}
public:
virtual std::string regn() const { return "???"; }
virtual ~Animal(){
cout << "Destructor animal"<<'\n';}
};
class Nevertebrate : public Animal{
public:
virtual std::string regn() const { return "nevertebrate";}
virtual ~Nevertebrate();
};
class Vertebrate: public Animal {
protected:
/* std::string m_name;
Vertebrate (std::string name)
:m_name {name} {} */
Vertebrate (std::string name)
: Animal {name} {}
public:
virtual std::string regn() const { return "vertebrate";}
virtual ~Vertebrate(){
cout<<"Destructor vertebrate"<<'\n';};
};
class bird: public Vertebrate {
public:
bird(std::string name)
: Vertebrate{ name }{}
void set_name (std::string nume){
m_name = nume;}
std::string get_name(){
return m_name;}
virtual std::string regn() const {return "pasare";}
virtual ~bird (){
cout << "destructor bird"<<'\n';}
};
template <class T>
class Atlas
{
private:
int m_length{};
T* m_data{};
public:
void SetLength(int j);
Atlas(int length)
{
assert(length > 0);
m_data = new T[length]{};
m_length = length;
}
Atlas(const Atlas&) = delete;
Atlas& operator=(const Atlas&) = delete;
~Atlas()
{
delete[] m_data;
}
void erase()
{
delete[] m_data;
m_data = nullptr;
m_length = 0;
}
T& operator[](int index)
{
assert(index >= 0 && index < m_length);
return m_data[index];
}
int getLength() const;
};
template <class T>
int Atlas<T>::getLength() const
{
return m_length;
}
template <class T>
void Atlas<T>::SetLength(int j){m_length = j;
}
int main()
{
Atlas<Bird> AtlasBird(10);
Bird b;
AtlasBird.SetLength(11);
AtlasBird[10] = b --- it gets a memoryleak from here.
return 0;
}
I want to overload the += operator so that i can insert a new object into my Atlas, (e.g. AtlasAnimal).
I tried with the SetLength function to increase the length, (e.g. AtlasAnimal.SetLength(11)) but when i try to assign AtlasAnimal[10] an object (e.g. Bird b) it drops a memory leak.
I'm sorry if there was a similar question answered, but i couldn't find anything that helps
Related
I have the generic class which can store a value and a type of the value encoded as a string.
#include <iostream>
#include <string>
#include <memory>
#include <cassert>
struct IValueHolder
{
virtual ~IValueHolder() = default;
virtual const std::string& getType() = 0;
virtual void setType(const std::string& t_type) = 0;
};
template<class T>
class ValueHolder : public IValueHolder
{
private:
T m_value;
std::string m_type;
public:
ValueHolder(T t_value) : m_value(t_value){}
virtual const std::string& getType() override
{
return m_type;
}
virtual void setType(const std::string& t_type) override
{
m_type= t_type;
}
const T& getValue() const
{
return m_value;
}
};
std::unique_ptr<IValueHolder> build_int_property()
{
auto p32{ std::make_unique<ValueHolder<int32_t>>(0) };
p32->setType("int32");
return std::move(p32);
}
int main()
{
auto v32 = dynamic_cast<ValueHolder<int32_t>*>(build_int_property().get());
assert(v32->getValue() == 0); // FAILS
assert(v32->getType() == "int32"); // FAILS
return EXIT_SUCCESS;
}
And I have another utility function build_int_property which builds an integer property. But unfortunately, the tests fail. Can anyone explain what is going wrong here?
I have a base class Animal and a derived class Bird : Animal. I use a template class that will store vectors of pointers to either Animal or Bird objects. I want to overload the += operator in such a way that I can insert a new animal right in the Atlas, so m_length = m_length + 1, pages.push_back(animal), just to get the idea.
Here's my template class:
template <class T>
class Atlas2 {
public:
int m_length;
std::list<T> pages;
Atlas2() { m_length = 0; }
~Atlas2() {}
void adauga(T data);
T operator+=(const T& data) {
this->m_length++;
this->pages.push_back(data);
return *this;
};
};
And here's the Animal/Bird classes:
class Animal {
protected:
std::string m_name;
public:
Animal() {}
Animal(std::string name) : m_name{name} {}
virtual void set_name(std::string name) { m_name = name; }
virtual std::string get_name() { return m_name; }
virtual std::string regn() const { return "???"; }
virtual ~Animal() { cout << "Destructor animal" << '\n'; }
};
class Bird : public Animal {
public:
bird() : animal() {}
bird(std::string name) : Animal{name} {}
void set_name(std::string nume) { m_name = nume; }
std::string get_name() { return m_name; }
std::string regn() const override { return "pasare"; }
~bird() { cout << "destructor pasare" << '\n'; }
};
However, I can't figure this out. When I use the overloaded += operator in main() like this:
Pasare *c = new Pasare{"vulture"};
Atlas2<Animal *> Atlas;
Atlas += c;
It shows me an error, that it couldn't convert Atlas<Animal *> to <Animal*>.
How should I implement this correctly? Any tip?
Note: The template works fine, I can store in my list pointers to either Animal or Birds without problems, and access their specific methods. I just can't figure out the += part.
You should return Atlas2<T> & not T:
Atlas2<T>& operator+=(const T& data) {
this->m_length++;
this->pagini.push_back(data);
return *this;
};
The basic problem is that you've declared your operator+= as returning a T, but the return statement in it is return *this;, which is an Atlas2<T>.
If you change the return type to Atlas2<T> &, it should work. That's what you would normally want to return from an operator+= anyways, though with your use, it doesn't matter much as you're ignoring the returned value.
I have a situation here...
I want to design a Factory where I can call a function with same name and no parameters but return different data Types. Based on the SubClassName I need to instantiate the Object.
Need help or lead on any design pattern to follow?
EDIT:
An abstract pseudo code...
class parent{
public:
virtual string getName() = 0;
//some virtual function.. not sure how to design. As the return type is dynamic.
*** getValue(){}
};
class A : public parent{
int x;
public:
virtual string getName(){ return "A";}
virtual int getValue(){retun x;}
};
class B : public parent{
string s;
public:
virtual string getName(){ return "B";}
virtual string getValue(){ return s;}
};
void main(){
string callingClass = "B";
parent * arrayPtrs[2];
arrayPtrs[0] = new A;
arrayPtrs[1] = new B;
for (loop through array, through iterator i){
if(arrayPtrs[i]->getName == callingClass ){
cout<<arrayPtrs[i]->getValue;
}
}
}
In C++ a function can only have one return type at a time, and you cannot change that dynamically.
However - as suggested by #mch - you can use template specializations. Keep in mind though, that this method is not dynamic. Your functions will be generated at compile time.
If I understood your question correctly, maybe this can be of help.
class MyObject1
{
//...
};
class MyObject2
{
//...
};
template<typename T>
struct Factory
{
constexpr static T gen();
};
template<>
struct Factory<MyObject1>
{
constexpr static MyObject1 gen()
{
return MyObject1(/*... whatever parameters you see fit ...*/);
}
};
template<>
struct Factory<MyObject2>
{
constexpr static MyObject2 gen()
{
return MyObject2(/*... whatever parameters you see fit ...*/);
}
};
int main()
{
auto myObj = Factory<MyObject1>::gen();
return 0;
}
Although this method seems fairly useless to me. You could simply call the desired constructor instead of this.
But then again, I'm not sure if this is what you thought of. If I made any mistakes please feel free, to correct me. I'll try to edit my answer best as I can.
EDIT:
To keep the virtual functionality too, the only way I can think of is type erasure: see https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Type_Erasure
The closest I could get to what you've asked for is this:
#include <iostream>
#include <string>
#include <any>
class parent {
public:
// you can use this too but I think type checking is more handy
// see in main function
/* virtual std::string getName() const = 0; */
virtual std::any getValue() const = 0;
};
class A : public parent {
public:
typedef int value_type;
private:
value_type x;
public:
A(value_type x) :
x(x)
{}
/* virtual std::string getName() const override { return "A"; } */
virtual std::any getValue() const override
{ return this->x; }
};
class B : public parent {
public:
typedef std::string value_type;
private:
value_type s;
public:
B(const value_type& s) :
s(s)
{}
/* virtual std::string getName() const override { return "B"; } */
virtual std::any getValue() const override
{ return this->s; }
};
int main(){
using callingClass = A;
parent* arrayPtrs[2];
arrayPtrs[0] = new A(42);
arrayPtrs[1] = new B("my string");
for (unsigned i = 0; i < sizeof(arrayPtrs) / sizeof(parent*); ++i)
{
// Note:
// dynamic cast will return nullptr if $callingClass
// is not a derived class
if (dynamic_cast<callingClass*>(arrayPtrs[i]))
std::cout << std::any_cast<callingClass::value_type>(arrayPtrs[i]->getValue()) << std::endl;
}
return 0;
}
I hope this one helps.
Note, that I used dynamic_cast to check the correct type. If you know a better solution, you can use that, too. But under these circumstances I couldn't think of any better.
EDIT2:
#include <iostream>
#include <string>
#include <tuple>
class some
{
using id = size_t;
template<typename T>
struct type { static void id() { } };
template<typename T>
static id type_id() { return reinterpret_cast<id>(&type<T>::id); }
template<typename T>
using decay = typename std::decay<T>::type;
template<typename T>
using none = typename std::enable_if<!std::is_same<some, T>::value>::type;
struct base
{
virtual ~base() { }
virtual bool is(id) const = 0;
virtual base *copy() const = 0;
} *p = nullptr;
template<typename T>
struct data : base, std::tuple<T>
{
using std::tuple<T>::tuple;
T &get() & { return std::get<0>(*this); }
T const &get() const& { return std::get<0>(*this); }
bool is(id i) const override { return i == type_id<T>(); }
base *copy() const override { return new data{get()}; }
};
template<typename T>
T &stat() { return static_cast<data<T>&>(*p).get(); }
template<typename T>
T const &stat() const { return static_cast<data<T> const&>(*p).get(); }
template<typename T>
T &dyn() { return dynamic_cast<data<T>&>(*p).get(); }
template<typename T>
T const &dyn() const { return dynamic_cast<data<T> const&>(*p).get(); }
public:
some() { }
~some() { delete p; }
some(some &&s) : p{s.p} { s.p = nullptr; }
some(some const &s) : p{s.p->copy()} { }
template<typename T, typename U = decay<T>, typename = none<U>>
some(T &&x) : p{new data<U>{std::forward<T>(x)}} { }
some &operator=(some s) { swap(*this, s); return *this; }
friend void swap(some &s, some &r) { std::swap(s.p, r.p); }
void clear() { delete p; p = nullptr; }
bool empty() const { return p; }
template<typename T>
bool is() const { return p ? p->is(type_id<T>()) : false; }
template<typename T> T &&_() && { return std::move(stat<T>()); }
template<typename T> T &_() & { return stat<T>(); }
template<typename T> T const &_() const& { return stat<T>(); }
template<typename T> T &&cast() && { return std::move(dyn<T>()); }
template<typename T> T &cast() & { return dyn<T>(); }
template<typename T> T const &cast() const& { return dyn<T>(); }
template<typename T> operator T &&() && { return std::move(_<T>()); }
template<typename T> operator T &() & { return _<T>(); }
template<typename T> operator T const&() const& { return _<T>(); }
};
using any = some;
class parent {
public:
// you can use this too but I think type checking is more handy
/* virtual std::string getName() const = 0; */
virtual any getValue() const = 0;
};
class A : public parent {
public:
typedef int value_type;
private:
value_type x;
public:
A(value_type x) :
x(x)
{}
/* virtual std::string getName() const override { return "A"; } */
virtual any getValue() const override
{ return this->x; }
};
class B : public parent {
public:
typedef std::string value_type;
private:
value_type s;
public:
B(const value_type& s) :
s(s)
{}
/* virtual std::string getName() const override { return "B"; } */
virtual any getValue() const override
{ return this->s; }
};
int main(){
using callingClass = A;
parent* arrayPtrs[2];
arrayPtrs[0] = new A(42);
arrayPtrs[1] = new B("my string");
for (unsigned i = 0; i < sizeof(arrayPtrs) / sizeof(parent*); ++i)
{
// Note:
// dynamic cast will return nullptr if $callingClass
// is not a derived class
if (dynamic_cast<callingClass*>(arrayPtrs[i]))
std::cout << arrayPtrs[i]->getValue()._<callingClass::value_type>() << std::endl;
}
return 0;
}
This snipped is in case you cannot use C++17 features, and is based on:
any class
Could anyone tell me why i get a compiling error in the "setFlyBehaviour" and "setQuackBehaviour" of the Duck class? (error : "term does not evaluate to a function taking 1 arguments")
this is an example of a strategy pattern from Head First Design Patterns (which is in Java that i translated here in C++). I introduced a Wrapper pattern in order to manage memory. (the wrapper class i'm using is from Mark Joshi, Option Pricing and Design Patterns)
Thanks!!!!!
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string>
#include <map>
#include <exception>
#include <vector>
using namespace std;
template< class T>
class Wrapper
{
//Taken From Mark Joshi, Designs patterns and derivatives pricing
public:
Wrapper()
{ DataPtr =0;}
Wrapper(const T& inner)
{
DataPtr = inner.clone();
}
Wrapper(const Wrapper<T>& original)
{
if (original.DataPtr !=0)
DataPtr = original.DataPtr->clone();
else
DataPtr=0;
}
~Wrapper()
{
if (DataPtr !=0)
delete DataPtr;
}
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;
};
/*****************************************************/
/***************** Interfaces ****************/
/*****************************************************/
class FlyBehaviour
{
private:
public:
virtual void fly() const = 0;
virtual FlyBehaviour* clone() const = 0;
};
class QuackBehaviour
{
private:
public:
virtual void quack() const = 0;
virtual QuackBehaviour* clone() const = 0;
};
/*****************************************************/
/***************** Implementations ***********/
/*****************************************************/
// -- FlyBehaviour
class FlyWithWings : public FlyBehaviour
{
public:
virtual void fly() const{
cout << "flying with wings" << endl;
}
virtual FlyBehaviour* clone() const {
return new FlyWithWings;
}
};
class FlyNoWay : public FlyBehaviour
{
public:
virtual void fly() const{
cout << "flying no way" << endl;
}
virtual FlyBehaviour* clone() const {
return new FlyNoWay;
}
};
// -- QuackBehaviour
class Quack : public QuackBehaviour
{
public:
virtual void quack() const{
cout << "Quacking here!" << endl;
}
virtual QuackBehaviour* clone() const{
return new Quack;
}
};
class Squeak : public QuackBehaviour
{
public:
virtual void quack() const{
cout << "Squeaking here!" << endl;
}
virtual QuackBehaviour* clone() const{
return new Squeak;
}
};
class Duck
{
private:
Wrapper<FlyBehaviour> flyBehaviour;
Wrapper<QuackBehaviour> quackBehaviour;
public:
void performQuack() const{
quackBehaviour->quack();
}
void performFly() const{
flyBehaviour->fly();
}
void setFlyBehaviour(const FlyBehaviour& mfly){
flyBehaviour(mfly);
}
void setQuackBehaviour(const FlyBehaviour& mquack){
quackBehaviour(mquack);
}
virtual void display() const{
}
};
class MallardDuck : public Duck
{
public:
virtual void display() const{
cout << "It looks like a Mallar" << endl;
}
};
class RedheadDuck : public Duck
{
public:
virtual void display() const{
cout << "It looks like a Redhead" << endl;
}
};
int main()
{
}
You were actually trying to call non-existent function instead of constructor.
There was also mistake in argument you were passing to setQuackBehaviour.
This should work:
void setFlyBehaviour(const FlyBehaviour& mfly){
flyBehaviour = mfly;
}
void setQuackBehaviour(const QuackBehaviour& mquack){
quackBehaviour = mquack;
}
It fails because Wrapper does not provide function call operator:
R T::operator ()(Arg1 a1, Arg2 a2, …)
And you are trying to make a call to Wrapper template:
flyBehaviour(mfly);
#werewindle like this ?
void reset(const QuackBehaviour& original){
if (DataPtr!= &original)
{
if (DataPtr!=0)
delete DataPtr;
DataPtr = (original.DataPtr !=0) ? original.DataPtr->clone() : 0;
}
}
I've been assigned the following template:
#include <map>
template <typename T>
class Catalog {
struct Item {
//..
};
std::map<int, Item*> items;
public:
Catalog(void);
Catalog(const Catalog&);
~Catalog(void);
bool IsEmpty(void) const;
int Size() const;
void Add(T*);
T* Remove(T*);
T* Find(T*);
typedef void (T::*pFunc) (const T&);
void Inspection(pFunc) const;
};
Next, there is an abstract Product class and three subclasses:
class Product {
protected:
unsigned int _id;
string _name;
public:
Product(const int& id, const string& name) : _id(id), _name(name) {};
virtual void Action(const Product& p) = 0;
virtual int hashCode() {
return _id*100;
};
unsigned int getId(void) const {return _id;};
string getName(void) const {return _name;};
};
class ProductA : public Product {
public:
ProductA(const int& id, const string& name) : Product(id, name) {};
virtual void Action(const Product& p) {
cout << "ahoj" << endl;
};
};
Finally, class ProductsCatalog that handles a Catalog instance:
class ProductsCatalog {
Catalog<Product> catalog;
public:
//..
void CatalogInspection(void) const {
catalog.Inspection(&Product::Action);
}
};
What I have trouble with is the Inspection method:
template <typename T> void Catalog<T>::Inspection(pFunc p) const {
for (std::map<int, Item*>::const_iterator it=items.begin(); it!=items.end(); ++it) {
it->second->Product->*p(*(it->second->Product));
}
};
I am getting the following error:
error C2064: term does not evaluate to a function taking 1 arguments
I've tried everything I could think of, without success. The following works as intended, but is obviously not abstract enough:
it->second->Product->Action(*it->second->Product);
Did you try
(it->second->Product->*p)(*(it->second->Product));
for calling the method?
The thread Calling C++ class methods via a function pointer seems to be related.