how to return a list of objects without destroying them - c++

How to fix the function 'func' so that it returns the objects without being destroyed?
function 'func' must add the objects to a list and return them but be destroyed
The Smoothy abstract class has a purely virtual description method (). DecoratorSmoothy
contains a smoothy, description () and getPret () methods return the description and price
aggregate smoothy.
SmoothyCuFream and SmoothyCuUmbreluta classes add the text “cu crema”
respectively “cu umbreluta” in the description of the smoothy contained. The price of a smoothy that has the cream increases by 2 euro, the one with the umbrella costs an extra 3 euro.
BasicSmoothy class is a smoothy without cream and without umbrella, method
description () returns the name of the smothy
#include <iostream>
#include <vector>
using namespace std;
class Smoothy {
private:
int pret=0;
public:
virtual string descriere() = 0;
int getPret(){
return pret;
}
void setPret(int a) {
pret += a;
}
};
class BasicSmooty : public Smoothy {
private:
string nume;
public:
BasicSmooty(string n) :
nume { n } {}
string descriere() {
return nume;
}
};
class DecoratorSmoothy : public Smoothy {
private:
Smoothy* smooty;
public:
DecoratorSmoothy() = default;
DecoratorSmoothy(Smoothy* n) :
smooty{ n } {}
string descriere() {
return smooty->descriere();
}
int getPret() {
return smooty->getPret();
}
};
class SmootyCuFrisca : public DecoratorSmoothy {
private:
BasicSmooty bsc;
public:
SmootyCuFrisca(string desc) :
bsc{ desc } {}
string descriere() {
setPret(2);
return bsc.descriere() + " cu frisca ";
}
};
class SmootyCuUmbreluta : public DecoratorSmoothy{
private:
BasicSmooty bsc;
public:
SmootyCuUmbreluta(string desc) :
bsc{ desc } {}
string descriere() {
setPret(3);
return bsc.descriere() + " cu umbreluta ";
}
~SmootyCuUmbreluta() {
cout << "rip";
}
};
vector<Smoothy*> func(void)
{
std::vector<Smoothy*> l;
SmootyCuFrisca a1{ "smooty de kivi" };
SmootyCuUmbreluta a2{ "smooty de kivi" };
SmootyCuFrisca a3{ "smooty de capsuni" };
BasicSmooty a4{ "smooty simplu de kivi" };
l.push_back(&a1);
l.push_back(&a2);
l.push_back(&a3);
l.push_back(&a4);
return l;
}
int main() {
vector<Smoothy*> list;
// Here when i call func() objects are distroyed
list = func();
return 0;
}

In func you are storing the address of function local variables in l. So when you return l from the function, all the Smoothy* are now pointing to invalid memory.
To fix this, you can allocate memory for each pointer you add to l, like this:
l.push_back(new Smoothy{a1}); // instead of l.push_back(&a1);
// etc. for a2, a3, ...
To really get away from this problem, consider not using pointers at all. If your design doesn't need it, you can get rid of the pointers, and you'll save yourself a lot of trouble.

Well, when a method returns, of course all local/automatic variables are destroyed. Under the late revision c++ changes, there is the return && modifier, which invokes move semantics, which means for not const local/automatic objects you return, it steals: clones the returned object, making a new object and copying all the primitives and object pointers, then sets the object pointers to null so they cannot be deleted/freed by the destructor. (Note that C free of a null pointer does nothing!) For const, of course, it must deep copy.

Related

Avoid creating named variables when pointer is required

I have been creating named variables in order to be able to pass their adress to a constructor that expects a pointer, but I want to be able to create them in a constructor or other function and then pass their address to the constructor that expects a pointer.
I am using C++ 20 and I have the following classes:
#include <iostream>
#include <string>
#include <vector>
#include <random>
using std::string, std::cout, std::cin, std::endl, std::vector;
class symbol {
public:
enum symbolKind {
null,
terminal,
sequence,
weighted,
random
};
protected:
symbolKind kind;
public:
virtual string evaluate() const = 0;
symbolKind getKind() {
return kind;
}
};
class nullSymbol : public symbol {
public:
nullSymbol() {
kind = symbol::null;
}
string evaluate() const override {
return "";
}
};
class terminalSymbol : public symbol {
private:
string termString;
public:
terminalSymbol(string pString) {
kind = symbol::terminal;
termString = pPhoneme;
}
string evaluate() const override {
return termString;
}
};
class sequenceSymbol : public symbol {
private:
vector<symbol*> symArray;
public:
sequenceSymbol(vector<symbol*> pArr) {
kind = symbol::sequence;
symArray = pArr;
}
string evaluate() const override {
string retStr = "";
for (symbol* current : symArray) {
retStr += current->evaluate();
}
return retStr;
}
};
class weightedSymbol : public symbol {
private:
float weight;
symbol* subSym;
public:
weightedSymbol(symbol* pSym, float pWeight) {
kind = symbol::weighted;
subSym = pSym;
weight = pWeight;
}
string evaluate() const override {
return subSym->evaluate();
}
float getWeight() {
return weight;
}
};
class randomSymbol : public symbol {
private:
vector<weightedSymbol*> symArray;
public:
randomSymbol(vector<weightedSymbol*> pArr) {
kind = symbol::random;
symArray = pArr;
}
string evaluate() const override {
float sum = 0.0;
for (weightedSymbol* current : symArray) {
sum += current->getWeight();
}
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(0.0, sum);
float randomResult = dis(gen);
float prev = 0;
for (weightedSymbol* current : symArray) {
if (randomResult < (prev += current->getWeight())) return current->evaluate();
}
}
};
I have been creating symbols like this:
terminalSymbol term_a("a");
terminalSymbol term_b("b");
sequenceSymbol seq_ab({ &term_a, &term_b});
cout << "ab test: " << seq_ab.evaluate() << endl;
But I would want to be able to do it like this or similar:
sequenceSymbol seq_ab_2({&terminalSymbol("a"), &terminalSymbol("b")});
cout << "ab test 2: " << seq_ab_2.evaluate() << endl;
This creates an error '&' requires l-value in Visual Studio.
This is a pretty simple example, often there are a lot more variables being created than this. In this case, the addresses are being passed to the std::vector<weightedSymbol*>() constructor; it's the same with the weightedSymbol() constructor which also expects a pointer. This should work not only for the constructor (it doesn't even need to work with the constructor itself if there is another way to achieve the same functionality), but I want a way to create heap objects in a function and then return a pointer to them that works in this situation. It might be that I need to change the classes themselves for this to work, they should just provide the same functionality.
In the end, I want to create these symbol objects dynamically based on user input.
I have searched online and tried using a bunch of different things but didn't manage to get the functionality I want working. What would be a good way to implement this? There is probably a common technique/idiom that I can use, if so, please explain it to me in detail so that I can use it in other projects too.
The objects you pass by pointers need to be destroyed somehow. In this snippet they will be destroyed automatically whenever you exit the block:
terminalSymbol term_a("a");
terminalSymbol term_b("b");
sequenceSymbol seq_ab({ &term_a, &term_b});
What should happen if you create objects without a named variable? Your classes never delete the objects that you pass by pointers, so that should be the caller responsibility to manage the lifespan of each object.
One solution for your problem is to wrap the objects into any sort of smart pointers. For example:
class sequenceSymbol : public symbol {
public:
sequenceSymbol(vector<shared_ptr<symbol>> pArr);
};
sequenceSymbol seq_ab_2({
std::make_shared<terminalSymbol>("a"),
std::make_shared<terminalSymbol>("b")
});

constructor inside a method c++

I have a constructor inside a method that I want to have access at all time
//ItemEditor.cpp
#include "ItemContainer.h"
void ItemEditor::CreateItem() {
ItemContainer* wornItems = new ItemContainer();
}
inside of my driver I call my method createItem();
//driver
int main(){
ItemEditor* createItem = new ItemEditor();
createItem->CreateItem();
}
afterwards I want to have access to backpack outside of the createItem
How can I accomplish that?
Make the item container a member variable so its scope is the life time of the object.
There is no reason to use dynamic allocation, so just use an instance of the ItemContainer instead of a pointer.
#include <iostream>
class ItemContainer {
int item = 0;
public:
void addItem(int i) {
item = i;
}
int getItem() {
return item;
}
};
class ItemEditor {
public:
ItemEditor() {
}
void createEditor() {
wornItems.addItem(3);
}
ItemContainer wornItems;
};
int main() {
ItemEditor editor;
int item = editor.wornItems.getItem(); //or some method
std::cout << item << std::endl;
editor.createEditor();
item = editor.wornItems.getItem(); //or some method
std::cout << item;
return 0;
}
You can also make the container private and use public methods to access its contents. You can see an example here
By backpack I assume whatever is returned by
createItem->CreateItem();
Why not just store it in a pointer since you used the new to allocate the object in a heap?
ItemContainer* ItemEditor::CreateItem() {
return new ItemContainer();
}
Main file:
int main(){
ItemEditor* createItem = new ItemEditor();
ItemContainer* backpack = createItem->CreateItem();
}
Also I want to suggest it is a better practice to provide a move semantic for ItemContainer and get rid of pointers. That way you are relying on RAII and stack for object destruction, less risk of memory-leak. Related article:
http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html
Here is a full compiling code:
//Header.h
#include <iostream>
class ItemContainer{
public:
void sayHello(){
std::cout << "HulloWorld!\n";
}
};
class ItemEditor{
public:
ItemEditor(){};
ItemContainer* ItemEditor::CreateItem(){
return new ItemContainer();
}
};
MainFile:
//main
#include "Header.h"
int main()
{
ItemEditor* createItem = new ItemEditor();
ItemContainer* backpack = createItem->CreateItem();
backpack->sayHello();
}

Can I use polymorphism to store different objects in an array with C++?

Im learning C++, and I am trying to do a little app. My app takes an informal ticket (without TAX) like this:
2
3 Mi_primera_tablet 7.95
1 El_general_en_su_laberinto Gabriel_García_Márquez 23.50
Where the first line is the number of items
In the second and third line= type of tax + title + price without TAX
The items can be of different types: books(TAX type 3), toys(TAX type 1)
All types inherit from the class article, but depending of the TAX type the price will be different (polymorphism).
I need to store all items (different types) in an array, how can I do it?
You can store pointers in the array.
Exapmle (c++11):
#include <iostream>
#include <vector>
#include <memory>
struct A {
int value;
};
struct B {
double item;
};
class Element {
public:
explicit Element(A a);
explicit Element(B b);
const A * AsA() const;
const B * AsB() const;
private:
class AbstractElement {
public:
virtual ~AbstractElement() {
}
protected:
AbstractElement() {
}
};
template <typename T>
struct ConcreteElement : public AbstractElement {
T body;
explicit ConcreteElement(T input_body)
: body(std::move(input_body)) {
}
};
std::unique_ptr<AbstractElement> element_;
};
Element::Element(A a)
: element_(new ConcreteElement<A>(a)) {
}
Element::Element(B b)
: element_(new ConcreteElement<B>(b)) {
}
const A * Element::AsA() const {
const auto concrete_element =
dynamic_cast<ConcreteElement<A> *>(element_.get());
return concrete_element ? &(concrete_element->body) : nullptr;
}
const B * Element::AsB() const {
const auto concrete_element =
dynamic_cast<ConcreteElement<B> *>(element_.get());
return concrete_element ? &(concrete_element->body) : nullptr;
}
int main() {
std::vector<Element> values;
values.push_back(Element(A{1}));
values.push_back(Element(B{1.5}));
values.push_back(Element(A{-5}));
values.push_back(Element(B{0}));
for (const auto & element : values) {
const auto p_a = element.AsA();
if (p_a) {
std::cout << "A: " << p_a->value << std::endl;
} else {
const auto p_b = element.AsB();
std::cout << "B: " << p_b->item << std::endl;
}
}
return 0;
}
output:
A: 1
B: 1.5
A: -5
B: 0
Maybe you can try boost::variant library, it act as a wrapper around anything. then you can store many boost::variant wrapper in an array
if I understood your question correctly, you need to know how to define an array of your base class with it's derived classes. If this is the case, you can do it by defining an array in the base class, which in your case would look something like this:
article ArrayName [n];
Books Books = new Books();
//do some thing with the books object
ArrayName[0] = Books;
All types inherit from the class article, but depending of the TAX
type the price will be different (polymorphism).
type or TAX type could be stored as a member in Class article.
No polymorphism is needed here.
The items can be of different types: books(TAX type 3), toys(TAX type
1)
Or you could store only the type (books, toys), and do a lookup in a table type | TAX-type, if the TAX types will always be the same for the full range of each type.
But if you really have or need a derived class for each type (for example to store different properties), you could call a virtual function in the derived classes CalcTax() for example.
An array with (baseclass*) pointers to the items could be created, and you can loop through that array, and call CalcTax() on each item, which will call the correct virtual function.
For example:
#include <iostream>
class Base
{
public:
virtual CalcTax() = 0;
};
class Type_1 : public Base
{
public:
virtual CalcTax() {std::cout << "Type_1\n";}
};
class Type_2
{
public:
virtual CalcTax() {std::cout << "Type_2\n";}
};
int main()
{
Base *arrItems[2]; // or better use std::vector<> etc.
Type_1 t1; // just a quick demo of polymorphism
Type_2 t2;
arrItems[0] = (Base*)&t1;
arrItems[1] = (Base*)&t2;
for (int i = 0; i < 2; ++i) {
arrItems[i]->CalcTax();
}
return 0;
}

How to transfer values set in privates of base class by an object of one derived class to an object of another derived class?

I have my main.cpp like this:
#include <iostream>
#include "curve1.h"
#include "curve2.h"
using namespace std;
int main()
{
Curve1 curve1Obj;
Curve2 curve2Obj;
curve1Obj.enterScores();
curve1Obj.calcAverage();
curve1Obj.output();
curve1Obj.curve();
curve1Obj.output(curve1Obj.new_getAverage1(), curve1Obj.new_getScore1());
curve2Obj.curve();
return 0;
}
Base class Score has two derived classes Curve1 and Curve2. There are two curve() functions, one is in Curve1 and other in Curve2 classes. getSize() returns the value of iSize.
My base class header score.h looks like this:
#ifndef SCORE_H
#define SCORE_H
class Score
{
private:
int *ipScore;
float fAverage;
int iSize;
public:
Score(
void enterScores();
void calcAverage();
void output();
void output(float, int*);
void setSize();
int getSize();
void setScore();
int *getScore();
float getAverage();
};
#endif
You can see that I have used curve1Obj to enter scores, calculate average and output. So if I call getSize() function with cuve1Obj, it gives the right size that I took from user in enterScores() function. Also the result is same if I call getSize() in score.cpp definition file in any of the functions (obviously).
.....
The problem is when I call curve() function of Curve2 class in main (line 23) with the object curve2Obj, it creates a new set of ipScore, fAverage and iSize (i think?) with garbage values. So when I call getSize() in curve() definition in curve2.cpp, it outputs the garbage.
.....
How can I cause it to return the old values that are set in curve1.cpp?
Here is my curve2.cpp
#include <iostream>
#include "curve2.h"
using namespace std;
void Curve2::curve()
{
cout << "getSize() returns: " << getSize() << endl; // out comes the garbage
}
Can I use a function to simply put values from old to new variables? If yes then how?
Well, basically your problem can't be easily solved the way it is.
Like you said:
1 - Don't use constructors of any type.
2 - Don't use vectors.
3 - Using dynamic new and delete etc. etc.
Use the constructors or stick with what G. Samaras and Richard Hodges said. You can only solve this that way.
There is limited information available here but I would say that your Score constructor has not initialised ipScore or iSize.
If you are hell-bent on using a pointer to a dynamically allocated array of ints for your score then at least null out the pointer in the constructor and test for null in the average function (i.e. no scores yet).
Better yet... use a std::vector of int for your scores.
Why are people still using new and delete? What the hell are they teaching in schools?
What I think you want is this:
#include <vector>
class Score {
public:
Score()
: _scores()
, _average(0)
{ }
void calcAverage() {
double total = 0;
if(auto s = _scores.size() > 0) {
for (const auto& v : _scores)
total += v;
total /= s;
}
_average = total;
}
virtual void curve() = 0;
protected:
// one of the few correct uses of 'protected' - giving limited access to data as interface to derived classes
const std::vector<double>& scores() const {
return _scores;
}
// or
std::vector<double> copyScores() const {
return _scores;
}
private:
// use doubles since you'll be doing floating point arithmetic
std::vector<double> _scores;
double _average;
};
class Curve1 : public Score {
public:
virtual void curve() override {
// custom curve function here
// written in terms of scores() or copyScores() if you want to make changes to the array
}
};
class Curve2 : public Score {
public:
virtual void curve() override {
// custom curve function here
// written in terms of scores();
}
};
You need to understand inheritance. Curve1 inherits from Score. Curve2 inherits from Score.
Now see this example:
#include <iostream>
class Base {
int x;
};
class A : public Base {
int a;
public:
void set_a(int arg) {
a = arg;
}
int get_a() {
return a;
}
};
class B : public Base {
int b;
public:
void set_b(int arg) {
b = arg;
}
int get_b() {
return b;
}
};
int main() {
A a_object;
a_object.set_a(4);
B b_object;
b_object.set_b(a_object.get_a());
std::cout << "a of a_object = " << a_object.get_a() << "\n";
std::cout << "b of b_object = " << b_object.get_b() << "\n";
return 0;
}
class A, has as members x and a. Class B has as members x and b.
When I create an instance of class A, I will two data members created internally, x and a.
When I create an instance of class A, I will two data members created internally, x and b.
But, the first x and the second are DIFFERENT. They are a different cell in the memory!
something like this:
class Score {
public:
Score()
: _scores(0)
, _size(0)
, _average(0)
{ }
// copy constructor
Score(const Score& rhs)
: _scores( new double[rhs._size] )
, _size(rhs._size)
, _average(rhs._average)
{
if (_size) {
for(int i = 0 ; i < _size ; ++i) {
_scores[i] = rhs._scores[i];
}
}
}
// ... and if copy constructor then always a copy operator
Score& operator=(const Score& rhs) {
// assignment in terms of copy constructor - don't repeat yourself
Score tmp(rhs);
swap(tmp);
return *this;
}
// pre c++11 we make our own swap.
// post c++11 we would make non-throwing move constructor and move-assignment operator
void swap(Score& rhs) {
// std::swap is guaranteed not to throw
std::swap(_scores, rhs._scores);
std::swap(_size, rhs._size);
std::swap(_average, rhs._average);
}
~Score()
{
delete[] _scores;
}
void calcAverage() {
double total = 0;
if(_size > 0) {
for (int i = 0 ; i < _size ; ++i)
total += _scores[i];
total /= _size;
}
_average = total;
}
virtual void curve() {};
private:
// use doubles since you'll be doing floating point arithmetic
double * _scores;
int _size;
double _average;
};
// rmember to override the copy operators and assignment operators of derived classes
// remember to call the base class's operator

How to return a class object by reference in C++?

I have a class called Object which stores some data.
I would like to return it by reference using a function like this:
Object& return_Object();
Then, in my code, I would call it like this:
Object myObject = return_Object();
I have written code like this and it compiles. However, when I run the code, I consistently get a seg fault. What is the proper way to return a class object by reference?
You're probably returning an object that's on the stack. That is, return_Object() probably looks like this:
Object& return_Object()
{
Object object_to_return;
// ... do stuff ...
return object_to_return;
}
If this is what you're doing, you're out of luck - object_to_return has gone out of scope and been destructed at the end of return_Object, so myObject refers to a non-existent object. You either need to return by value, or return an Object declared in a wider scope or newed onto the heap.
You can only use
Object& return_Object();
if the object returned has a greater scope than the function. For example, you can use it if you have a class where it is encapsulated. If you create an object in your function, use pointers. If you want to modify an existing object, pass it as an argument.
class MyClass{
private:
Object myObj;
public:
Object& return_Object() {
return myObj;
}
Object* return_created_Object() {
return new Object();
}
bool modify_Object( Object& obj) {
// obj = myObj; return true; both possible
return obj.modifySomething() == true;
}
};
You can only return non-local objects by reference. The destructor may have invalidated some internal pointer, or whatever.
Don't be afraid of returning values -- it's fast!
I will show you some examples:
First example, do not return local scope object, for example:
const string &dontDoThis(const string &s)
{
string local = s;
return local;
}
You can't return local by reference, because local is destroyed at the end of the body of dontDoThis.
Second example, you can return by reference:
const string &shorterString(const string &s1, const string &s2)
{
return (s1.size() < s2.size()) ? s1 : s2;
}
Here, you can return by reference both s1 and s2 because they were defined before shorterString was called.
Third example:
char &get_val(string &str, string::size_type ix)
{
return str[ix];
}
usage code as below:
string s("123456");
cout << s << endl;
char &ch = get_val(s, 0);
ch = 'A';
cout << s << endl; // A23456
get_val can return elements of s by reference because s still exists after the call.
Fourth example
class Student
{
public:
string m_name;
int age;
string &getName();
};
string &Student::getName()
{
// you can return by reference
return m_name;
}
string& Test(Student &student)
{
// we can return `m_name` by reference here because `student` still exists after the call
return stu.m_name;
}
usage example:
Student student;
student.m_name = 'jack';
string name = student.getName();
// or
string name2 = Test(student);
Fifth example:
class String
{
private:
char *str_;
public:
String &operator=(const String &str);
};
String &String::operator=(const String &str)
{
if (this == &str)
{
return *this;
}
delete [] str_;
int length = strlen(str.str_);
str_ = new char[length + 1];
strcpy(str_, str.str_);
return *this;
}
You could then use the operator= above like this:
String a;
String b;
String c = b = a;
Well, it is maybe not a really beautiful solution in the code, but it is really beautiful in the interface of your function. And it is also very efficient. It is ideal if the second is more important for you (for example, you are developing a library).
The trick is this:
A line A a = b.make(); is internally converted to a constructor of A, i.e. as if you had written A a(b.make());.
Now b.make() should result a new class, with a callback function.
This whole thing can be fine handled only by classes, without any template.
Here is my minimal example. Check only the main(), as you can see it is simple. The internals aren't.
From the viewpoint of the speed: the size of a Factory::Mediator class is only 2 pointers, which is more that 1 but not more. And this is the only object in the whole thing which is transferred by value.
#include <stdio.h>
class Factory {
public:
class Mediator;
class Result {
public:
Result() {
printf ("Factory::Result::Result()\n");
};
Result(Mediator fm) {
printf ("Factory::Result::Result(Mediator)\n");
fm.call(this);
};
};
typedef void (*MakeMethod)(Factory* factory, Result* result);
class Mediator {
private:
Factory* factory;
MakeMethod makeMethod;
public:
Mediator(Factory* factory, MakeMethod makeMethod) {
printf ("Factory::Mediator::Mediator(Factory*, MakeMethod)\n");
this->factory = factory;
this->makeMethod = makeMethod;
};
void call(Result* result) {
printf ("Factory::Mediator::call(Result*)\n");
(*makeMethod)(factory, result);
};
};
};
class A;
class B : private Factory {
private:
int v;
public:
B(int v) {
printf ("B::B()\n");
this->v = v;
};
int getV() const {
printf ("B::getV()\n");
return v;
};
static void makeCb(Factory* f, Factory::Result* a);
Factory::Mediator make() {
printf ("Factory::Mediator B::make()\n");
return Factory::Mediator(static_cast<Factory*>(this), &B::makeCb);
};
};
class A : private Factory::Result {
friend class B;
private:
int v;
public:
A() {
printf ("A::A()\n");
v = 0;
};
A(Factory::Mediator fm) : Factory::Result(fm) {
printf ("A::A(Factory::Mediator)\n");
};
int getV() const {
printf ("A::getV()\n");
return v;
};
void setV(int v) {
printf ("A::setV(%i)\n", v);
this->v = v;
};
};
void B::makeCb(Factory* f, Factory::Result* r) {
printf ("B::makeCb(Factory*, Factory::Result*)\n");
B* b = static_cast<B*>(f);
A* a = static_cast<A*>(r);
a->setV(b->getV()+1);
};
int main(int argc, char **argv) {
B b(42);
A a = b.make();
printf ("a.v = %i\n", a.getV());
return 0;
}
It isn't really good practice to return an initiated object as it does go out of scope. There are rare instances that this is the desired option. It actually can be done if the class is a referencing counting smart pointer or some other smart pointer.
How does a reference-counting smart pointer's reference counting work?