Make multiple class object members of another class in C++ - c++

I am having a trouble of putting multiple class objects as member of another class. To be more specific: lets assume we have 2 classes, A and B and class A is nested. I want the main function to have an array with 3 objects of class B. The first object will have 2 objects of class A, the second object will have 5 objects of class A and the third object will have 7 objects of class A. How can i do that? Below is one of my thoughts:
Class A{
private:
int variable;
public:
A(){
cout<< A created! <<endl;
}
~A(){
cout<< A destructed! <<endl;
}
};
Class B{
private:
A array[6]; //It will always create 6 elements of class A...
public:
B(){
cout<< B created! <<endl;
}
~B(){
cout<< B destructed! <<endl;
}
};
int main(){
B* array[3];
for (i = 0 ; i <= 2 ; i++)
{
array[i] = new B(); //Every B element in array have 6 elements of class A
}
}
Thanks in advance!

If you can't use vectors.. (which you should).. here is a working example that shows what you want to do with arrays and manual memory management. https://ideone.com/KihmON
Note: there is no error handling in here. If this was your program it's very unlikely new will ever fail, but for larger objects it can. If you thrown an error in main before your delete statements, those objects will never get deleted. That is why vector is preferred, in the case of errors, it will get cleaned up when it leaves scope no matter what.
#include <iostream>
class A
{
private:
int variable;
public:
A()
{
std::cout << "A created!" << std::endl;
}
~A()
{
std::cout << "A destructed!" << std::endl;
}
};
class B
{
private:
size_t arrayOnHeapSize; // size of array on heap
A* arrayOnHeap; // memory must be allocated before this is used.
public:
B(size_t arrSize) :
arrayOnHeapSize(arrSize)
{
arrayOnHeap = new A[arrSize]; // must deallocate memory manually, use "delete[]" arrays of objects
std::cout<< "B created with size" << arrSize << '!' << std::endl;
}
~B()
{
delete[] arrayOnHeap; // must deallocate memory manually
std::cout << "B destructed! Wouldn't have had to do memory management manually if I had used a vector!" << std::endl;
}
B(const B&) = delete; // If you need to make a copy, you'll have to make a copy constructor that performs a deep copy or adds some (ugly) reference counting logic. Could also opt to implement a move constructor. If you copied this as is, the pointer will get copied, one B will get destructed freeing the memory, then the other B will have a dangling pointer and try to free that upon destruction. No good.
};
int main()
{
B* arrayOfB[3];
arrayOfB[0] = new B(2);
arrayOfB[0] = new B(5);
arrayOfB[0] = new B(7);
delete arrayOfB[0]; // must deallocate manually, using "delete" instead of "delete[]" because these are each 1 object, not arrays.
delete arrayOfB[1];
delete arrayOfB[2];
// Don't need to delete arrayOfB as it is a local on the stack and will be taken care of as the function exits.
}

You can make B a parameterised type (I think that's the correct term):
template<int a>
class B {
A array[a];
};
int main() {
B<2> b1;
B<5> b2;
B<7> b3;
}
However they can't be in an array as B<2> is a different type to B<7> etc.

Related

Unwanted call to constructor and destructor when using pointers in objects

I have declared a few classes like this:
class foo
{
public:
foo(); /* valid constructor that works as intended */
void define(bar* B)
{
b=nullptr;
if(B!=nullptr)
{
/* b=new bar; this line deleted */
b=B;
}
~foo();
bar* AccessBar()
{
return b;
}
private:
bar* b; // a simple pointer
}
class bar
{
public:
bar(foo* F=nullptr)
{
f=nullptr;
if(F!=nullptr)
{
f=new foo[2];
for(int i=0; i<2; i++)
{
f[i]=F[i];
}
}
};
foo F(int i)
{
return f[i];
}
~bar()
{
cout << "enter bar destructor" << endl;
delete s; // works usually out of this context
cout << "deletion of s completed" << endl;
};
int toto()
{
/* something that works usually */
};
private:
class_another *s;
foo* f; // will serve as an array
}
(nota: those declarations are in fact made in several header and source files)
Then assume I have made valid declarations and affections (I verified it):
1 foo f[2];
2 bar b1,b2;
3 f[0].define(&b2);
4 f[1].define(&b2);
5 b1(f); /* now b1.f is a new pointer to a copy of f*/
I have several problems that I wish to solve:
calls in line 3 and 4 leads to a call to bar constructor I wish not to make because I think it might cause memory leaks (?)
How can I avoid this? (using &b1 and &b2?).
after these declarations, everything is well-assigned as I could check with cout BUT:
call to b1.F(0).AccessBar()->toto() works correctly, but a call to the destructor of bar is made and following lines are ignored during execution.
call to f(0).AccessBar()->toto() works correctly, doesn't call the destructor of bar and the rest of the programm is executed correctly.
What has been done so far:
Before, foo was written in this fashion:
class foo
{
public:
bar AccessBar()
{
return *b;
}
private:
bar* b; // a simple pointer
}
And called b1.F(0).AccessBar()->toto(). The problem was the same as above and I thought the problem was due to dereferencing.
I have someone suggesting me a solution using std::shared_ptr<bar> instead of bar from <memory> library, but it is a huge problem because I have to rewrite the code entirely and would prefer to avoid it if any alternative exists. Also I think it's worth knowing if it exists or not.
Also I've checked with printing in my destructor that the pointer is still really pointing to an actual bar object when called. It is the case.
After the scope is done, my destuctor is called, as "enter bar destructor" line confirms.
~bar()
{
cout << "enter bar destructor" << endl;
delete s;
cout << "deletion of s completed" << endl;
}
The second message is not read and the s still points to the object it is supposed to point to. Even an empty destructor blocks the programm from going past its call, however.

Adding a string-type class member causes base class function to be called instead of child

Why does the following code print 0, but if you comment out "std::string my_string" it prints 1?
#include <stdio.h>
#include <iostream>
class A {
public:
virtual int foo() {
return 0;
}
private:
std::string my_string;
};
class B : public A {
public:
int foo() {
return 1;
}
};
int main()
{
A* a;
if (true) {
B b;
a = &b;
}
std::cout << a->foo() << std::endl;
return 0;
}
I also understand that changing std::string to std:string* also causes the code to print 1, as does removing the if-statement, though I don't understand why any of that is true.
EDIT: This seems to be due to a dangling pointer. Then what's the standard pattern in C++ to do something like this in Java:
Animal animal;
boolean isDog = false;
// get user input to set isDog
if (isDog) {
animal = new Dog();
} else {
animal = new Cat();
}
animal.makeNoise(); // Should make a Dog/Cat noise depending on value of isDog.
Problem
The program has Undefined Behaviour. b is only in scope inside the body of the if. You can't count on logical results when accessing a dangling pointer.
int main()
{
A* a;
if (true) {
B b; // b is scoped by the body of the if.
a = &b;
} // b's dead, Jim.
std::cout << a->foo() << std::endl; // a points to the dead b, an invalid object
return 0;
}
TL;DR Solution
int main()
{
std::unique_ptr<A> a; // All hail the smart pointer overlords!
if (true) {
a = std::make_unique<B>();
}
std::cout << a->foo() << std::endl;
return 0;
} // a is destroyed here and takes the B with it.
Explanation
You can point a at an object with a dynamic lifetime
int main()
{
A* a;
if (true) {
a = new B; // dynamic allocation
} // b's dead, Jim.
std::cout << a->foo() << std::endl;
delete a; // DaANGER! DANGER!
return 0;
}
Unfortunately delete a; is also undefined behaviour because A has a non-virtual destructor. Without a virtual destructor the object pointed at by a will be destroyed as an A, not as a B.
The fix for that is to give A a virtual destructor to allow it to destroy the correct instance.
class A {
public:
virtual ~A() = default;
virtual int foo() {
return 0;
}
private:
std::string my_string;
};
There is no need to modify B because once a function is declared virtual, it stays virtual for its children. Keep an eye out for final.
But it's best to avoid raw dynamic allocations, so there is one more improvement we can make: Use Smart pointers.
And that brings us back to the solution.
Documentation for std::unique_ptr
Documentation for std::make_unique

What use instead of make_shared_from_this in constructor?

I need to register object in global list. I know I can't use make_shared_from_this in constructor - what do I use instead?
vector<shared_ptr<A> > alpha;
struct A : enable_shared_from_this<A>
{
int x;
A():x(9)
{
//alpha.push_back(shared_from_this());
//alpha.push_back(shared_ptr<A>(this));
}
};
1) first push back would result in crash:
ibc++abi.dylib: terminating with uncaught exception of type std::__1::bad_weak_ptr: bad_weak_ptr
2) second push back would result in segmentation fault
You cannot use shared_from_this from constructor and you actually don't need shared_from_this here. You can just write something like create function.
vector<shared_ptr<A> > alpha;
// in struct A
static shared_ptr<A> create()
{
shared_ptr<A> pointer = make_shared<A>();
alpha.push_back(pointer);
return pointer;
}
put constructor in private location and use any trick from How do I call ::std::make_shared on a class with only protected or private constructors?
Is the global vector just meant to list all the objects in memory or do you actually delete objects from the vector. In the later case ForEveR gave a good answer. In the former case, if the code would work, none of the shared_ptr you create would get deleted until the end of the program because they are stored in a global vector. In this case just keep it simple and use old style pointers and add them at the constructor and delete in destructor. For efficiency it's better to change the vector data type. E.g.,
#include<iostream>
#include<memory>
#include<unordered_set>
class A;
std::unordered_set<A*> alpha;
class A{
public:
A(): x(9)
{
alpha.insert(this);
}
~A(){
alpha.erase(this);
}
private:
int x;
};
Example test:
int main(){
std::shared_ptr<A> a= std::make_shared<A>();
std::cout << "Number of objects: " << alpha.size() << std::endl;
{
std::shared_ptr<A> a1= std::make_shared<A>();
std::shared_ptr<A> a2= std::make_shared<A>();
std::cout << "Number of objects: " << alpha.size() << std::endl;
}
std::cout << "Number of objects: " << alpha.size() << std::endl;
}
Number of objects: 1
Number of objects: 3
Number of objects: 1

If the memory allocated be freed after constructor throw exception

I know Object *pObject=new Object contain two steps:
operator new to allocate memory
call object's constructor.
and call delete pObject:
call object's destruct;
operator delete to free memory.
But when new Object process, if the step 2 throw exception, if the operator delete be called to free memory by system?
No, the destructor is not called. As the object isn't constructed properly it would be unsafe to call the destructor. However if any member objects have been constructed fully then they are destructed (as the object is complete).
Some people recommend against throwing in constructors, I believe it is better than zombie states which is akin to error codes and makes verbose code. So long as you follow RAII you should be fine (each resource is managed by it's own object). Before you throw in the constructor make sure that you clean up anything you've half done, but again, if you're using RAII that should be nothing.
The following outputs "B":
#include <iostream>
struct B {
~B() { std::cout << "B" << std::endl; }
};
struct A {
A() : b() { throw(1); }
~A() { std::cout << "A" << std::endl; }
B b;
};
int main() {
try {
A *a = new A;
delete a;
} catch(int a) {}
}
Edit:
The above isn't what you asked, yes the delete operator is called, http://www.cplusplus.com/reference/new/operator%20delete[] says:
"These deallocation functions are called by delete-expressions and by new-expressions to deallocate memory after destructing (or failing to construct) objects with dynamic storage duration."
This could be tested by overriding the operator delete.
Yes, the operator delete will be called to release the memory allocated.
The program below can prove that:
#include <iostream>
using std::cout;
using std::endl;
class A {
public:
A() { cout << "A() at " << this << endl; throw 1; }
~A() { cout << "~A() at " << this << endl; }
};
int main(int argc, char *argv[]) {
int N = 3;
for (int i = 0; i < N; ++i) {
try {
new A;
} catch (int a) {
// pass
}
}
return 0;
}
Running this program on my system, I find that the result printed out are like this:
A() at 0x2170010
A() at 0x2170010
A() at 0x2170010
Obviously, the destructors are NOT call because NO
~A() at 0x2170010
lines are printed out.
And the operator delete are surely called because the addresses of the three objects are exactly the same.

Why aren't these shared_ptrs pointing to the same container?

I have a class Model:
class Model
{
...
boost::shared_ptr<Deck> _deck;
boost::shared_ptr<CardStack> _stack[22];
};
Deck inherits from CardStack.
I tried to make _stack[0] point to the same thing that _deck points to by going:
{
_deck = boost::shared_ptr<Deck>(new Deck());
_stack[0] = _deck;
}
It seems that the assignment to _deck of _stack[0] results in a copy of _deck being made. (I know this because modifications to _stack[0] do not result in modifications to _deck.) How can I get them to point to the same thing?
Ok - no copy constructor is being called. I have verified this by implementing it and seeing if it gets called - it doesn't.
However - I have a function that operates on CardStack objects:
void TransferSingleCard(CardStack & src, CardStack & dst, Face f)
{
if( !src._cards.empty() )
{
src._cards.back().SetFace(f);
dst.PushCard(src._cards.back());
src._cards.pop_back();
}
}
Now - when I call:
{
TransferSingleCard(*_stack[DECK], _someotherplace, FACEDOWN);
std::cout << *_stack[DECK];
std::cout << *_deck;
}
I get this output (where std::cout on a CardStack will print out the size of that stack):
Num(103) TOP
Num(104) TOP
... so I've concluded (incorrectly?) that _stack[DECK] points to something different.
The Deck
class Deck : public CardStack
{
public:
Deck(int numsuits=2, StackIndex index = NO_SUCH_STACK );
Deck::Deck( const Deck & d);
int DealsLeft() const;
void RecalcDealsLeft();
private:
int _dealsleft;
};
Not clear what you are asking about - consider this code:
#include <iostream>
#include "boost/shared_ptr.hpp"
using namespace std;
struct A {
virtual ~A() {
cout << "destroyed" << endl;
}
};
struct B : public A {
};
int main() {
boost::shared_ptr<B> b( new B );
boost::shared_ptr<A> a;
a = b;
}
Only one "destroy" message appears, indicating that no copy has been made.
This example - derives from #Neil's answer, tries to emulate what you say is happening. Could you check that it works as expected (A and B have the same count) on your system.
Then we could try and modify this code or your code until they match.
#include <boost/shared_ptr.hpp>
#include <iostream>
class A {
public:
virtual ~A()
{
std::cerr << "Delete A" << std::endl;
}
int _count;
void decrement()
{
_count --;
}
};
class B : public A {
public:
virtual ~B()
{
std::cerr << "Delete B" << std::endl;
}
};
int main()
{
boost::shared_ptr<B> b(new B);
b->_count = 104;
boost::shared_ptr<A> a;
a = b;
a->decrement();
std::cerr << "A:" << a->_count << std::endl;
std::cerr << "B:" << b->_count << std::endl;
return 0;
}
EDIT:
So from the comment, we know the original pointers are correct, so now we need to trace.
Either:
log pointers to see when they change.
Use watchpoints in a debugger to see when the pointer changes.
Use a third shared pointer to see which pointer is changed.
Introduce a function that changes both pointers at the same time.
I think the problem is that you're assigning between different types here. boost::shared_ptr is a template and templates are not polymorphic even if the type in them is. So what's happening is that your compiler sees the assignment from boost::shared_ptr<Deck> to boost::shared_ptr<CardStack> and notices that it can make the assignment by calling the copy constructor for CardStack to duplicate the Deck object.
I think what you want the assignment to look like is something like this:
_stack[0] = boost::static_pointer_cast<CardStack>(_deck);
Which will do the conversion the way you expect it to.
I think you may want shared_array for _stack . . . Take a look at the documentation on shared_ptr;from boost.org, specifically:
http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm
"Normally, a shared_ptr cannot
correctly hold a pointer to a
dynamically allocated array. See
shared_array for that usage."
Also, be aware of the T* get() function (not to be used without good reason) which returns the raw pointer being held by the managed pointer (shared_ptr in this case).