0

I have been programming some in Java earlier, and i'm now trying to learn c++, but having trouble with understanding pointers, deep-/shallow copy, copy constructor, assignment operator and those c++ specific things. It's not really the code itself, its more how they relate and why / when they are needed.

So i tried to make a easy example for myself, so i would get the hang of it but i can't get it to work, it keeps crashing.

Here's the code:

class A
{
    public:
        A();
        A(B* v);
        A(const A &o);
        virtual ~A();
        void print(std::ostream &o);
        A& operator=(A& o);
        friend std::ostream &operator<<(std::ostream &stream, A p);
    protected:
    private:
        B *value;
};

void A::print(std::ostream &o)
{
    value->print(o);
}

A& A::operator=(A& o)
{
    std::cout << "Operatorn"<< std::endl;
    this->value = o.value;
}

A::A()
{
    //ctor
}
A::A(B* v)
{
    this->value = v;
    std::cout << "B konstruktor" << std::endl;
}

A::A(const A& o)
{
    std::cout << "Kopieringskonstruktor" << std::endl;
    this->value = o.value;
}

A::~A()
{
    if(value!=NULL) delete value;
    std::cout << "Deletar value" << std::endl;
}

--------------------------------------------------

class B
{
    public:
        void print(std::ostream &o);
        B();
        B(int i):value(i){}
        virtual ~B();
    protected:
    private:
        int value;
};

--------------------------------------------------

std::ostream &operator<<(std::ostream &stream, A p)
{
    p.print(stream);
    return stream;
}

int main()
{
    vector<A> vecA;
    ostream_iterator<A> it(cout);
    vecA.push_back(A(new B(5)));
    vecA.push_back(A(new B(10)));
    copy(vecA.begin(), vecA.end(),it);
    return 0;
}

Edit 1

Some clarification, a similar problem to this is a homework assignment for me. Where i should have a holder-class A containing the value *B. And B is inherited to C and D, enabling me to place both class C and D into value *B.

I simplified and striped the code from this, since i didn't think it was relevant to the issue i'm having with memory and assignment.

  • If you're planning on storing dynamic allocations in c++ objects (1) understand the [Rule of Three](http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)), and then (2) don't do it like this. Either use a smart pointer such as `std::shared_ptr<>` or seriously consider whether or not dynamic allocation is warranted *at all* (there are times when it is, and this is arguably not one of them). – WhozCraig Sep 07 '13 at 10:18
  • The major difference of object representation in C++ and Java is that: every object in Java you can see or use is just the reference/handle, which is equivalent to the object pointer of reference in C++. – JackyZhu Sep 07 '13 at 10:23
  • Your `A& A::operator=(A& o)` should `return *this;` and also rather take a `const A& o`. There are probably other problems with the raw pointers. Anyway you should probably read [What is The Rule of Three?](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) – gx_ Sep 07 '13 at 10:26
  • C++ doesn't have deep vs shallow copies, only copies and pointers. If you understand how array indexes work, you're most of the way to understanding how pointers work. C++'s references are pointers behind a slightly different contract that allows you to behave as though you were referring directly to what is pointed to. – kfsone Sep 07 '13 at 10:27

1 Answers1

0

You've made a good decision when you decided to work with the vector of objects:

vector<A> vecA;

which should yield clean and easily maintainable code, yet for some reason you started making things more complicated than necessary. Let's start with overriding operator=... why? usually the default operators will suffice, if you override it you should have a really good reason to do so.

Another wrong decision was when you made class A to have a member of type B*.. why? what kind of relationship is between A and B ? Does A requires existence of object of type B? If yes, then let C to have a reference to an existing object with automatic storage duration:

class C {
public:
    C(const B& bRef) : b(bRef) { }
private:
    B& b;
}

If it is "has" / "contains" / "consists of" type of relation, it will be probably much more reasonable to have an object with automatic storage duration as a member and in case it needs to be initialized (in your case B's constructor requires int), let class C construct this object rather than caller:

class C {
public:
    C(int foodForB) : b(foodForB) { }
private:
    B b;
}

which would yield the following change: A(new B(5)) ~> A(5) and save you a lot of work and prevent A LOT of possible problems in future.

Avoid doing the memory management on your own ALWAYS when it's possible. Likewise avoid the dynamic allocation ~> take advantage of objects with automatic storage duration instead (see RAII).

LihO
  • 41,190
  • 11
  • 99
  • 167
  • To answer why i made this structure of having a holder class of A just containing a B value is because i simplified the code i'm working on to get a better overview. So i more easily can pinpoint what i'm doing wrong. Doing this i didn't show what relationship A and B has, it should be like this: A is a class holder containing B with is inherited by C and D. So i can add both class C and D to value B in class A. – Stefan Annell Sep 07 '13 at 11:04