Issue with polymorphism with smart pointers and vectors c++ - c++

I am currently trying to learn c++ and I am having an issue when trying to create a vector which iterates through several different objects whom all inherit from the same base class with smart pointers.
I parse a file and create the objects and insert them into the vector depending on the character parsed but I keep getting the error:
Error C2664 'std::unique_ptr<Test *,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': cannot convert argument 1 from 'std::unique_ptr<Test2,std::default_delete<_Ty>>' to 'std::nullptr_t'"
Code is as follows:
class Test {
public:
virtual ~Test(){}
virtual int update() {}
};
class Test2 : public Test {
private:
int a;
public:
Test2() {
}
Test2(int n) {
a = n;
}
int update() override {
return a;
}
};
class Test3 : public Test {
private:
int a;
public:
Test3() {
}
Test3(int n) {
a = n;
}
int update() override {
return a;
}
};
class Test4 : public Test {
private:
int a;
public:
Test4() {
}
Test4(int n) {
a = n;
}
int update() override {
return a;
}
};
class manager {
private:
std::vector<std::unique_ptr<Test*>> vList;
std::ifstream lvlFile;
public:
std::string tmp;
manager() {
}
~manager() {
}
void init(const char *path) {
lvlFile.open(path, 0);
while (lvlFile.eof() != true) {
std::getline(lvlFile, tmp);
for (char& a : tmp) {
switch (a) {
case 'w':
vList.emplace_back(std::make_unique<Test2>(2));
break;
case 'g':
vList.emplace_back(std::make_unique<Test3>(3));
break;
}
}
}
}
void print() {
for (auto& i : vList) {
std::cout << (*i)->update() << std::endl;
}
}
};
manager *m;
int main() {
m = new manager();
m->init("lvl.txt");
_getch();
}
Maybe I have misunderstood something crucial here but I have been looking around and found no real answers so any pointers to this would be most welcome!

Change std::vector<std::unique_ptr<Test*>> to std::vector<std::unique_ptr<Test>>.
std::unique_ptr<Test*> is a pointer to pointer (Test**).

Related

How to make a generic template C++ pointer?

Assume the snippet below. How can I make this compiling/working? I do not want to move print to the String/Float class, because in my real world situation this function is combining a lot of data.
So basically I want a pointer/member to "any type (in this case string/float)" then use it, and call dynamically something else (in this case print)?
I assume that this does not work (among others) because it cannot determine at compile time which type T of ptr will have at compile time.
What is the general pattern to solve such kind of problems?
#include <iostream>
template<typename T>
class AbstractClass {
virtual T getValue()=0;
};
class StringClass : public AbstractClass<std::string> {
std::string getValue() override {
return "A";
}
};
class FloatClass : public AbstractClass<float> {
float getValue() override {
return 1;
}
};
class Processor {
public:
AbstractClass<T>* ptr;
void doIt() {
ptr=new StringClass();
print(ptr->getValue());
delete ptr;
ptr=new FloatClass();
print(ptr->getValue());
delete ptr;
}
void print(std::string i) {
std::cout << "String "<<i<<std::endl;
}
void print(float i) {
std::cout << "Float "<<i<<std::endl;
}
}
int main() {
Processor a;
a.doIt();
}
If you want an object that's 'one of' a given set of types, you can use std::variant<Ts...>. Mathematically, it represents discriminated/tagged union. This way, you don't need a pointer, neither a base class. Example:
#include <iostream>
#include <variant>
class StringClass {
std::string getValue() override {
return "A";
}
};
class FloatClass {
float getValue() override {
return 1;
}
};
using ClassWithGetValue = std::variant<StringClass, FloatClass>;
class Processor {
public:
ClassWithGetValue v;
void doIt() {
v = StringClass();
std::visit([&](auto&& v1) {
print(v1.getValue());
});
v = FloatClass();
std::visit([&](auto&& v1) {
print(v1.getValue());
});
}
void print(std::string i) {
std::cout << "String "<<i<<std::endl;
}
void print(float i) {
std::cout << "Float "<<i<<std::endl;
}
}
int main() {
Processor a;
a.doIt();
}

Access child class functions from a vector of a parent class without downcasting

How can one access child class functions from a vector of a parent class without downcasting?
example:
class a {
public:
...
};
class b : public a {
double output() { // both child class have memeber function called output,
// but they return different data type.
return 0;
}
};
class c : public a {
bool output() { return false; }
};
// main
vector<a> vec;
b obj;
c obj2;
vec.push_back(obj);
vec.push_back(obj2);
for (int i = 0; i < vec.size(); i++) {
cout << vec[i].output();
}
Error:
error: no member function called "output" found in a
I have tried function overridding:
class a{
public:
auto output()
};
This approach don't work because I sometimes need to pass multiple parameters and this function doesn't allow that and will throw me the error: Function output expected 0 parameters, received x parameters.
It is possible like this
#include <iostream>
#include <vector>
struct result
{
enum
{
BOOL,
DOUBLE
} tag;
union ret {
double d;
bool b;
} r;
};
std::ostream &operator<<(std::ostream &s, const result &r)
{
switch (r.tag)
{
case result::DOUBLE:
s << r.r.d;
break;
case result::BOOL:
s << r.r.b;
break;
default:
break;
}
return s;
}
class a
{
public:
virtual result output() = 0;
};
class b : public a
{
result output() override
{
result r{result::DOUBLE, 132.};
return r;
}
};
class c : public a
{
result output() override
{
result r{result::BOOL, false};
return r;
}
};
int main(int argc, char const *argv[])
{
std::vector<a *> vec;
a *obj = new b;
a *obj2 = new c;
vec.push_back(obj);
vec.push_back(obj2);
for (int i = 0; i < vec.size(); i++)
{
std::cout << vec[i]->output() << std::endl;
}
return 0;
}
but its ugly. even more then

upcasting variable in derived class c++

How to change the type of a inherited variable in the derived class?
I have the following classes:
class Position;
class StonePosition;
class Position {
public:
Position() {}
};
class StonePosition : public Position {
int count;
public:
StonePosition(const int count) { this->count = count; }
int getCount() { return this->count; }
void setCount(int count) { this->count = count; }
friend ostream& operator<<(ostream&, StonePosition);
};
class Board {
protected:
Position* crrPos;
public:
Board() { }
Position* getCrrPos() { return crrPos; }
void setCrrPos(Position* pos) { crrPos=pos; }
};
class StoneBoard : public Board {
public:
StoneBoard(const int &count) { this->crrPos=new StonePosition(count); } //<----------------
StonePosition* getCrrPos() { return (StonePosition*)crrPos; }
void setCrrPos(StonePosition* pos) { crrPos=pos; }
};
Place in which the problem is marked by an arrow. I need to change the type of a variable from Position to StonePosition in the StoneBoard class. I found an option that can be used upcasting, but it works only within a single method, and I need to change the variable for the entire class.
The problem was solved, look at my answer.
The variable "crrPos" is not of type Position it is of type pointer to Position and this is significant because a pointer to Position can point to a Position or a class derived from Position without losing anything.
If you design your classes well, and make use of virtual functions, you can usually avoid the need to upcast entirely.
#include <iostream>
class Base {
public:
virtual void foo() { std::cout << "Base::foo()\n"; }
virtual bool isDerived() const { return false; }
};
class Derived : public Base {
public:
void foo() override { std::cout << "Derived::foo()\n"; }
bool isDerived() const { return true; }
};
int main() {
Base* crrPos = new Derived;
crrPos->foo();
bool isDerived = crrPos->isDerived();
std::cout << isDerived << '\n';
delete crrPos;
}
Live demo: http://ideone.com/UKcBaA
The problem has been solved, I just use the projection ((StonePosition*)Position*):
#include <iostream>
using namespace std;
class Position;
class StonePosition;
class Position {
public:
Position() {}
};
class StonePosition : public Position {
int count;
public:
StonePosition(const int count) { this->count = count; }
int getCount() { return this->count; }
void setCount(int count) { this->count = count; }
friend ostream& operator<<(ostream&, StonePosition);
};
template <typename TPos> class TBoard {
protected:
TPos* crrPos;
public:
TBoard() { }
TPos* getCrrPos() { return crrPos; }
void setCrrPos(TPos* pos) { crrPos=pos; }
};
class Board {
protected:
Position* crrPos;
public:
Board() { }
Position* getCrrPos() { return crrPos; }
void setCrrPos(Position* pos) { crrPos=pos; }
};
class StoneBoard : public Board {
public:
StoneBoard(const int &count) { this->crrPos=new StonePosition(count); }
Position* getCrrPos() { return crrPos; }
void setCrrPos(Position* pos) { crrPos=pos; }
};
int main(){
StoneBoard s(7);
cout<<((StonePosition*)s.getCrrPos())->getCount();//<----right here
system("pause");
return 0;
}
And its working nice :)

c++ runtime instantiation of member parameter

As the title says I would like to initiate a Store object whose type is determined at runtime only. I initially went for a virtual class, 2 derived classes but quickly faced the need for templates.
The class O has a pointer to an interface BaseStore for these Store objects. Moreover since I also need to call the right functions for the Derived classes Store1 and Store2, I used a dynamic cast in a template function of the interface.
Since I am new to c++, I wonder if this design has flaws and if there is any place for improvements. Thanks for your expertise!
#include <iostream>
using namespace std;
struct BaseStore {
virtual ~BaseStore() {}
template<typename S> void test() const;
};
struct Store1 : public BaseStore {
Store1(int j) { this->i = j; }
void test() const { cout << i << endl; }
private:
int i = 1;
};
struct Store2 : public BaseStore {
Store2(string s) { this->i = s; }
void test() const { cout << i << endl; }
private:
string i = "2";
};
template<typename S> void BaseStore::test() const
{
dynamic_cast<const S&>(*this).test();
}
class O {
public:
O(int i) {
this->type = i;
switch (this->type) {
case 1: basestore = new Store1(42); break;
case 2: basestore = new Store2("lol"); break;
}
}
~O() { delete basestore; }
void test() const {
switch (this->type) {
case 1: basestore->test<Store1>(); break;
case 2: basestore->test<Store2>(); break;
}
}
private:
int type;
BaseStore* basestore;
};
I believe virtual functions and the factory pattern will help here, as in:
struct BaseStore
{
virtual ~BaseStore() = default;
virtual void test() const = 0;
BaseStore() = default;
BaseStore(BaseStore const&) = delete;
BaseStore(BaseStore&&) = delete;
BaseStore& operator=(BaseStore&&) = delete;
BaseStore& operator=(BaseStore const&) = delete;
};
struct Store1 : public BaseStore {
Store1(int j) : i(j) {}
void test() const override { std::cout << i << std::endl; }
private:
int i = 1;
};
struct Store2 : public BaseStore {
Store2(std::string s) : i(std::move(s)) {}
void test() const override { std::cout << i << std::endl; }
private:
std::string i = "2";
};
class O {
public:
O(int i) : type(i), basestore(StoreFactory(i)) {}
void test() const { basestore->test(); }
private:
static std::unique_ptr<BaseStore> StoreFactory(int i)
{
switch (i)
{
case 1: return std::unique_ptr<Store1>(new Store1(42));
case 2: return std::unique_ptr<Store2>(new Store2("lol"));
default: throw std::runtime_error("Don't know what kind of Store you want");
}
}
int type;
std::unique_ptr<BaseStore> basestore;
};

Adapter pattern in C++, with non-virtual adapted methods

I want to create an adapter class in C++, but the interface that I want to adapt to has several non-virtual methods. Can I still use the regular adapter pattern?
#include <iostream>
using namespace std;
class NewInterface{
public:
int methodA(){ cout << "A\n"; }
virtual int methodB(){ cout << "B\n"; }
};
class OldInterface{
public:
int methodC(){ cout << "C\n"; }
int methodD(){ cout << "D\n"; }
};
class Old2NewAdapter: public NewInterface {
public:
Old2NewAdapter( OldInterface* a ){ adaptee = a; }
int methodA(){ return adaptee->methodC(); }
int methodB(){ return adaptee->methodD(); }
private:
OldInterface* adaptee;
};
int main( int argc, char** argv )
{
NewInterface* NI = new Old2NewAdapter( new OldInterface() );
NI->methodA();
NI->methodB();
return 0;
}
If I have this setup, the output will be "A D" instead of "C D" as it should.
So how can I adapt OldInterface to NewInterface, without rewriting NewInterface so that all methods are virtual?
Can you introduce another class? If you can then you can replace functions that use a NewInterface with an even NewerInterface:
class NewerInterface
{
public:
int methodA()
{
// preconditions
int const result = doMethodA();
// postconditions
return result;
}
int methodB()
{
// preconditions
int const result = doMethodB();
// postconditions
return result;
}
private:
virtual int doMethodA() = 0;
virtual int doMethodB() = 0;
};
class Old2NewerInterface : public NewerInterface
{
public:
explicit Old2NewerInterface(OldInterface& x) : old_(&x)
private:
virtual int doMethodA() { return old_->methodC(); }
virtual int doMethodB() { return old_->methodD(); }
private:
OldInterface* old_;
};
class New2NewerInterface : public NewerInterface
{
public:
explicit New2NewerInterface(NewInterface& x) : new_(&x)
private:
virtual int doMethodA() { return new_->methodA(); }
virtual int doMethodB() { return new_->methodB(); }
private:
NewInterface* new_;
};