Initializing an object in c++ - c++

A.hh
#ifndef A_HH
#define A_HH
#include <iostream>
#include <string>
using namespace std;
class A {
private:
int size;
string name;
public:
A();
~A();
int Load(int, string);
int getSize();
string getName();
/* data */
};
#endif
A.cc:
#include "A.hh"
A::A() {
}
int A::Load(int _size, string _name) {
size = _size;
name = _name;
return 0;
}
int A::getSize() {
return size;
}
string A::getName() {
return name;
}
A::~A() {
}
B.hh:
#ifndef B_HH
#define B_HH
#include "A.hh"
#include <string>
class B {
private:
A* objectA;
public:
B();
B(A*);
~B();
A* getA();
/* data */
};
#endif
B.cc:
#include "B.hh"
B::B() {
}
B::B(A* obj) {
objectA = obj;
}
A* B::getA() {
return objectA;
}
B::~B() {
}
C.cc
#include "C.hh"
C::C() {
}
int C::doSomething() {
cout<<"size = "<<getA()->getSize()<<endl;
cout<<"name = "<<getA()->getName()<<endl;
return 0;
}
C::~C(){
}
C.hh
#ifndef C_HH
#define C_HH
#include "B.hh"
class C : public B {
public:
C();
~C();
int doSomething();
/* data */
};
#endif
main.cc
#include "A.hh"
#include "B.hh"
#include "C.hh"
int main() {
A* objA = new A();
objA->Load(1, "Hello Drew Dormann :)");
B* objB = new B(objA);
C* objC = new C();
objC->doSomething();
return 0;
}
Why am I getting a segfault on doSomething()?
I'm using the child of B to handle the object parsed into B. Also I have to use B's child to handle A because this is part of something much bigger and this is the only way to simplify it.
I don't understand why this happens.

There seems to be a misconception of how objects work and are constructed behind this question.
C* objC = new C();
Creates brand new C. The C constructor does absolutely nothing beyond allocating storage, so absolutely nothing is initialized. Because C inherits from B, C's constructor will call the default constructor for B, which does nothing, but calls the default constructor for its parent, A.
A's default constuctor does not initialize name and size so their values are undefined. B's default constuctor does not initialize objectA so it is undefined, leading to the segfault.
This C was created by new comes out of some pool of memory, typically the heap, and needs to be returned to this pool with delete when no longer needed. If it is not the program will lose the memory used by C.
The same sample can be performed without dynamic allocation.
C objC;
Creates a C, but does it on the stack. When the stack unrolls at the end of the function or code block (search term: variable scope) the C will be popped off and automatically destroyed. This is typically the better way to operate as it requires no additional memory management. The C looks after itsef and can be considered "fire-and-forget."
Back on topic...
objC->doSomething();
Do something calls the getA method inherited from B which dutifully returns the uninitialized objectA. objectAis promptly used to call getSize with objectA as the concealed this parameter. Since Crom only knows what objectA is actually pointing at it would be a minor miracle if this->size wasn't somewhere crash-provoking.
If the OP expects
A* objA = new A();
objA->Load(1, "Hello Drew Dormann :)");
and
B* objB = new B(objA);
to have some bearing on the state of C. The OP is incorrect. objA and objB are their own entities. They are different objects and every object has its own state.
In order to have C initialize B with something other than the default constructor, you need your C constructor to look more like this:
C::C(A* obj) : B(obj)
{
}
This assigns a pointer to A passed into C to B, using B's B(A*); constructor.
C::C(A* obj,
int size,
string name) : B(obj, size, name)
{
}
B::B(A* obj,
int size,
string name) : A(size, name)
{
}
Cascades all of the parameters needed to fully specify a C all the way down to A.
As B needs to have objectA initialized, I recommend removing B and C's default constructors to force initialization to a meaningful value. If B and C require default constructors for some other purpose, such as storage in a standard container, either getA() needs to be a lot smarter or B's default constructor must initialize objectA to some safe value.
This still leaves the great question of why B contains a pointer to a parent. I'll leave that to the OP to work out.
And while The OP is at it, I recommend reading this: What is The Rule of Three?. Because the next question is likely to be "Dude! Who deleted my objectA"?
Also using namespace std in a header is very super bad. Read here: Why is "using namespace std" considered bad practice?

Your problem is that objectA in objC points to invalid memory hence in doSomething() you are trying to call the member access operator on an invalid pointer. You can change the default constructor of B to construct an object and have objectA point to it, make sure to free your memory as well!
#include <iostream>
#include <string>
/*#################
// !! class A !! //
#################*/
class A
{
private:
int size = 0;
std::string name;
public:
int Load(int, const std::string&);
int getSize() { return size; }
std::string getName() { return name; }
};
int A::Load(int _size, const std::string &_name)
{
size = _size;
name = _name;
return 0;
}
/*#################
// !! class B !! //
#################*/
class B
{
private:
A* objectA;
public:
B() : objectA(new A()) { }
B(A* obj) : objectA(new A(*obj)) { }
A* getA() { return objectA; }
virtual ~B() { delete objectA; }
};
/*#################
// !! class C !! //
#################*/
class C : public B
{
public:
C() = default;
int doSomething();
};
int C::doSomething()
{
// Problem: objectA points to invalid memory
std::cout << "size = " << getA()->getSize() << std::endl;
std::cout << "name = " << getA()->getName() << std::endl;
return 0;
}
/*#################
// !!! main !!! //
#################*/
int main()
{
A* objA = new A();
objA->Load(1, "Hello Drew Dormann :)");
B* objB = new B(objA);
C* objC = new C();
objC->doSomething();
// free your memory!!!
delete objA;
delete objB;
delete objC;
return 0;
}

Related

Can a parent class which is reinterpreted as a child class use the child's functions in its functions?

I want to call the child's function from parent's function in reinterpreted class, like below.
Example
#include <iostream>
class A {
public:
void func1() {
// some code
func2();
// some code
}
protected:
virtual void func2() {
printf("class A\n");
}
};
class B : public A {
protected:
virtual void func2() {
printf("class B\n");
}
};
int main() {
A* ab = new A();
ab->func1(); // this print "class A"
B* bab = reinterpret_cast<B*>(ab);
bab->func1(); // this also print "class A"
// I want to print "class B" when I use bab->func1()
}
In this situation, Is there any way to print class B using the reinterpreted class bab without redefining func1?
For C++ polymorphism to kick in, you must create an instance of the derived class somewhere, but you can store a pointer to the base class. Using the base-class pointer will dispatch to the overridden functions of the derived class. So your definition of A and B is fine, your usage in the main function is not. reinterpret_cast is not intended for this.
#include <iostream>
#include <memory>
class A {
public:
void func1() {
// some code
func2();
// some code
}
protected:
virtual void func2() {
printf("class A\n");
}
};
class B : public A {
protected:
virtual void func2() {
printf("class B\n");
}
};
int main() {
{
// This works, but don't do this. Naked "new" is not modern C++ and dangerous.
A* ab = new B();
ab->func1();
delete ab;
}
{
// VARIANT 2: use smart pointers
std::unique_ptr<A> ab = std::make_unique<B>();
ab->func1();
}
{
// VARIANT 3: A non-smart pointer is okay, as long as it
// 1. references an existing allocated object
// 2. the pointer does not outlive the object it points to
B b;
A* ab = &b;
ab->func1();
}
{
// VARIANT 4: Like Variant 3, but with reference instead of pointer
B b;
A& ab = b;
ab.func1();
}
}
Output
class B
class B
class B
class B
https://godbolt.org/z/8e5E85nx5
EDIT: Try to avoid allocation with new. Any memory allocated in this fashion must be freed by you using delete and it is very easy to forget (I did when I first wrote this answer, kinda proving my point). Even if you do delete the memory at the end of your function, there is the possibility that your code never reaches this statement, e.g. if exceptions are thrown somewhere between new and delete.Here is some further reading:
Why is it a bad idea to use 'new'?
Why should C++ programmers minimize use of 'new'?

C++ Abstract class pointer in method

So I have a c++ project that I'm working on and I'm trying to understand an other guys code but all I get are errors and confusion about c++ abstract classes.
So What I have is a header file a cpp file and a main program.
I want to create an abstract class pointer and then pass it to a method that initializes it to a subclass and then back in the main program I can use it as the subclass:
main.cpp:
#include "a.h"
#include <iostream>
using namespace std;
void parse(A* a){
a = new B();
a->foo();
}
int main() {
A* a;
parse(a);
a->foo();
}
a.h:
class A{
public:
virtual void foo() const = 0;
virtual ~A(){ }
};
class B : public A{
public:
void foo() const override;
};
class C : public A{
public:
void foo() const override;
};
a.cpp
#include <iostream>
#include "a.h"
void B::foo() const{
std::cout << "B" << std::endl;
}
void C::foo() const{
std::cout << "C" << std::endl;
}
Basically here I think I should cee a B but I get a segmentation error or the program exits without printing anything.
Thank you for your help!
In main you have uninitialized pointer a
int main() {
A* a;
parse(a);
a->foo();
}
So this statement
a->foo();
results in undefined behavior.
As for the function parse
void parse(A* a){
a = new B();
a->foo();
}
then it deals with its local variable a. Changing the local variable does not affect the original pointer declared in main.
You need to declare the parameter as having a referenced type
void parse(A* &a){
a = new B();
a->foo();
}
In this case the pointer a declared in main will be passed to the function by reference and the function will change the original pointer a.
Besides the issue of undefined behviour described in Vlad's answer, your example also leaks memory, even if the pointer in main was correctly initialised.
I recommend an alternative solution. Instead of modifying the pointer through a reference, I recommend to not use owning bare pointers. Instead, return the pointer, and use a smart pointer for ownership:
std::unique_ptr<A>
parse(){
auto a = std::make_unique<B>;
a->foo();
return a;
}
int
main() {
auto a = parse();
a->foo();
}

how to create object on 1>stack only and not on heap and 2>heap only not on stack

To create object on heap only->
1>is there anything wrong in the code
class B
{
~B(){}
public:
void Destroy()
{
delete this;
}
};
int main() {
B* b = new B();
b->Destroy();
return 0;
}
why you cant create object of class b on stack
2>
class B
{
B(){}
public:
static B* Create()
{
return new B();
}
};
int main() {
//B S;
B* b = B::Create();
return 0;
}
3>how to create object only on stack and not on heap
If you want to create object only in Heap make destructor as private. Once the destructor is made Private, the code will give compiler error in case on object creation on stack. If you do not use new the object will be created on stack.
1) Object creation only on Heap
class B
{
~B(){}
public:
void Destroy()
{
delete this;
}
};
int main() {
B* b = new B();
b->Destroy();
return 0;
}
Nothing seems to be wrong with above code, If you try to create the object on stack B b1 it will give compiler error.
2) For restricting the object creation on heap, Make operator new as private.
You code
class B
{
B(){}
public:
static B* Create()
{
return new B();
}
};
int main() {
//B S;
B* b = B::Create();
return 0;
}
This code is still creating object on Heap/Free store as it is using new.
3) To create object only on stack not on heap, the use of new operator should be restricted. This can be achieved making operator new as private.
class B
{
Private:
void *operator new(size_t);
void *operator new[](size_t);
};
int main() {
B b1; // OK
B* b1 = new B() ; // Will give error.
return 0;
}
Look at Concrete Data Type idiom: To control object's scope and lifetime by allowing or disallowing dynamic allocation using the free store (heap)

Inheritance and derived attribute disappearing in C++

I'm quite new to the concept of inheritance, and to C++ too, so my problem may be really stupid...
class A {
public :
A() {}
A(string name) {name_ = name}
private :
string name_;
}
class B : public A {
public :
B() {}
B(string name, int number) {
name_ = name;
number_ = number;
}
private :
string name;
int number;
}
class C {
public :
C() {}
void addClass(int id, A* a) {
map[id] = a;
}
private :
Hash_Map<int, A*> map;
}
void main() {
C* c = new C();
for (int i = 0; i < 10; i++) {
B* b = new B("randomName", 50);
c->addClass(i, b); //1st problem
delete b; //2nd problem
}
}
1st problem : shouldn't "map" in "c" keep the attribute "number" from the class "B"? I know I put A* in parameter, but if I had several class that derived from A, how should I do it?
2nd problem : All of my attributes in "map" seem to get random values when I delete "b". I'm guessing the problem is that I need to copy "b" into a new object, but how can I do it if I have "A*" as my addClass() parameter? My pointer b seems to be converted into its parent class
EDIT : had to change several things in my code that I forgot...
Bunch of problems:
1) No initializing members within a class declaration! (Your edit fixed this)
class B : public A {
public :
B() : name("A"), number(0) {} // initialize in constructor. that's what they are for!
private :
string name;
int number;
}
(Repeat that for A's declaration as well)
2)
You're storing a copy of the pointer to A (that was passed in as argument to addClass)in your map, not the actual object.
So, your map holds: 100 -> pointer to b
Then you delete whatever b points to. What would you think map[100] contains now?
A pointer to garbage! So, don't delete the pointer outside! Let C take care of it.
3) (My previous answer had a glaring error and someone voted it up. So, I'll keep the earlier part and point out my mistake)
Don't use pointers unless you need to. Save yourself some work. Go play the guitar or read some of Herb Sutter's articles!
void main() {
// don't use pointers and require that you delete them (unless you need to)
B b; // default constructor is called automatically. it is destroyed for you, by the compiler
// at the end of its scope (in this case, closing brace of main() )
C c;
c.addClass(100, b);
}
Let's fix C too. Can we get rid of those nasty pointers?
class C {
public :
C() {}
void addClass(const int id, const A a) { // use const, its a good habit!
map[id] = a;
}
private :
Hash_Map<int id, A a> map;
}
Now, what's wrong with this? Not just extra copies; when you pass b as argument to addClass by value, the compiler is gonna copy the A portion of b! So, we lostb`'s data (and overrides)!
So, we absolutely have to use pointers (references are dangerous, since they're deleted at scope exit).
What's important is that you make C owns the deletion.
So your code would now look like:
class C {
public :
C() {}
~C() {
for(pair<int, A*>& p : map) // C++11 syntax, yay!
delete p.second; // here's where you clean up. not in main.
}
void addClass(const int id, const A* a) {
map[id] = a;
}
private :
Hash_Map<int, A*> map;
}
void main() {
B* b = new B(); // back to square 1!
C c;
c.addClass(100, &b);
} // no memory leaks
But I hate taking care of deletion you say.. Fear not, we have shared_ptr!
#include <memory>
using namespace std;
typedef shared_ptr<A> Aptr;
class C {
public :
C() {}
~C() {
cout << "Drinking a beer coz i use shared_ptr";
}
void addClass(const int id, Aptr& a) {
map[id] = a;
}
private :
Hash_Map<int, Aptr> map;
}
void main() {
Aptr b(new B());
C c;
c.addClass(100, b);
} // still no memory leaks
Hope that helps.

Why a dynamically allocate object failed to be freed?

I know it should be a trivial question but need to find out why.
The following code compiled by failed with
a.out(93143) malloc: *** error for object 0x7fff5af8293f: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
codes:
#include <iostream>
using namespace std;
class A
{
};
class B
{
private:
A a;
public:
B(){a=*new A();}
~B(){delete &a;}
};
int main()
{
B b;
}
According to the immediate comments, I realized that the dynamically allocated object in "new" immediately lost its owner after assigning to "a". Now if I do want an object instead of a pointer to "A", what is the best solution?
Because your member variable is not a pointer. You're not storing the dynamically allocated object you're assigning a copy of it to A a; and leaking the dynamically allocated one.
Change class B to:
class B
{
private:
A* a;
public:
B(){a= new A();}
~B(){delete a;}
};
or better yet
class B
{
private:
A a;
public:
B() {}
~B(){}
};
In case you really need a dynamically allocated object, I would like to propose this final solution using smart pointers (you'll need C++11 or boost for this):
#include <memory>
#include <iostream>
class A
{
public:
A() { std::cout << "Hi" << std::endl; }
~A() { std::cout << "Bye" << std::endl; }
};
class B
{
public:
B(): a(new A()) {};
//~B() {} <-- destructor is no longer needed, the unique_ptr will delete the object for us
private:
std::unique_ptr<A> a;
};
int main(int argc, char* argv[])
{
B b;
}
You can see that the constructor and destructor for A is called here.