Inheritance and derived attribute disappearing in C++ - 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.

Related

How to access inherited class attribute from a third class?

The goal of the code structure below is to be able to store pointers to objects of any class inherited from 'A'.
When I run this code, I get 0 written out, but what I'm trying to access is the 'B' object's 'num' value, which is 1. How can I do that?
As far as I know, when you create an inherited class's object, you create an object of the parent class too automatically. So can I somehow access the parent class object from it's child and set it's class member to match?
See minimal reproducible example below.
Update: Virtual functions solved the problem.
#include <iostream>
class A
{
public:
int num;
A()
{
num = 0;
}
};
class B : public A
{
public:
int num;
B()
{
num = 1;
}
};
class C
{
public:
A* ptr_array[2];
C()
{
ptr_array[0] = new B();
}
void print()
{
std::cout << ptr_array[0]->num << std::endl;
}
};
int main()
{
C* object_c = new C();
object_c->print();
return 0;
}
The problem is that you define a member num in A, and another member num in B. So an object of type B has two members called num, and you're leaving it to the compiler to choose which one to use -- which it does, according to logical rules which may be unfamiliar to you.
If you remove the line in num; from the definition of B, the code will work as you intend.
Your array is a red herring. You are only using one pointer. Might just as well have it as a member for the sake of the example.
I suppose you might need something like this (note, untested code).
#include <memory>
#include <iostream>
class A {
public:
A() : m_num(0) {} // use this instead of assignment in the c'tor body
virtual int getNum() { return m_num; } // this is **the** way to use inheritance
virtual ~A() = default; // required
private:
int m_num;
};
class B : public A {
public:
B() : m_otherNum(1) {}
virtual int getNum() { return m_otherNum; } // does something different from A
private:
int m_otherNum; // you could also call it m_num, but for clarity I use a different name
};
class C {
public:
C() : m_a (std::make_unique<B>()) {} // note, use this instead of new B
void print() {
std::cout << m_a->getNum() << std::endl;
}
private:
std::unique_ptr<A> m_a; // note, use this instead of A* m_a;
};
I have no way of knowing if this is really what you need (or you think you need). This is how inheritance is supposed to be used in object-oriented programming. You can use it in various other ways and produce correct (as far as the language definition is concerned) programs. But if this is the case, then (public) inheritance is likely not the best tool for the job.

class member which is pointer to another class , c++

can s.one please help me to understand what I'm doing wrong in this process, so that I don't have access to my vector "vect"
#include <iostream>
#include <vector>
class A
{
private :
public :
A() {}
};
class B
{
private :
std::vector<A*> vect;
public :
B() {}
void func(){
std::cout << vect.size() <<std::endl;
}
};
class C
{
private :
B* b ;
public :
C() { }
void func (){
b->func();
}
};
int main (){
C c;
c.func();
return 0 ;
}
I expect to get "0" as an output but it seems like the vector hasn't been acceded so I get unrelevant number "17591314330723" !!!!
class C
{
private :
B* b ;
public :
C() { }
void func (){
b->func();
}
};
Looking at just this class; you can see that b is never assigned. In addition to that it's a pointer. This means that when you call b->func() you're trying to call func() on a random piece of memory. This is undefined behavior and you're unlucky that it didn't just crash (since it hides the problem).
Your options are to either assign b to a value; which I'm not going to explain how to do; your C++ book should cover that; or to change it to be not a pointer; (ie remove the *) which will create a new B for you when you create a C.

Initializing an object in 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;
}

Creating derived class instance using base class instance

I have a base class instance, there is a derived class that inherits from the base class, I want to transform the base instance into derived instance, (if possible without copying anything (maybe sending to the derived class a reference of the base class)) how can I achieve that?
Note: I need this because I'm using factory design pattern which identify the derived class needed to be created using a parameter located in the base instance.
//class A
//class B: public A (pure virtual)
//class C: public B
B BFactory::makeB(A &a) {
int n=a.getN();
if(n==1){
return new C();
}
}
Thanks.
Consider the case of the car.
You can treat a Lamborghini as a car.
You can treat a Yugo as a car.
You can treat a car as a Lamborghini if it is a Lamborghini. In C++ this means a pointer to car that really points to a Lamborghini. In order to get a Lamborghini pointer back out of the car pointer you should use dynamic_cast. If the car does not point to a Lamborghini, dynamic_cast will return NULL. This keeps you from trying to pass off a Yugo as a Lamborghini and blowing the Yugo's engine.
But when the Lamborghini is being treated as a car, it can only do car things. If you copy a Lamborghini into a car, you strip out all Lamborghini-ness forever. It's gone.
Code time!
This, I'm afraid cannot be done:
//class A
//class B: public A (pure virtual)
//class C: public B
B BFactory::makeB(A &a) {
int n=a.getN();
if(n==1){
return new C();
}
}
C is being copied into a B and the B is being returned. B would need a constructor that took a C, but the point is moot. B cannot be instantiated if it's pure virtual. For now we'll ignore the leak that would be new C()
Also can't use a reference for this job, pretty much the same problem, so you're trapped into returning a pointer
B * BFactory::makeB(A &a) {
int n=a.getN();
if(n==1){
return new C();
}
}
Now I'm going to make a suggestion: Build the make function into B and handle the case where A doesn't map to anything recognized by B.
class B: public A
{
public:
virtual ~B(){}
static B * makeB(A & a)
{
switch(a.getN())
{
case 1:
return new C();
}
return NULL;
}
};
But this leads to another recommendation: Why should B know anything? And What is the point of A at this level? Why is A storing build codes for classes two or more steps down the hierarchy? Bad from a maintenance point of view. The point of objects is they know who they are and how to manipulate themselves. Short-circuiting this leads to pain.
class B: public A
{
public:
virtual ~B(){}
virtual B* makeB() = 0;
};
Now B only makes Bs, needs no help from A, and those who extend B are stuck with figuring out how to make themselves--a task they should know better than anyone else. Much safer because there is never any possibility of a code unrecognised by B for a new class.
class C: public B
{
public:
B* makeB()
{
return new C();
}
};
class D: public B
{
public:
B* makeB()
{
return new D();
}
};
Edit: Traditional factory
You're asking for an abstract factory. For that you need nothing. You don't even need a class. You certainly don't need a class A. The goal of this sort of factory is the caller knows nothing about the class. By providing an A, the caller needs to know how to make an A or have another factory that makes an A.
First a bit of set-up in a header file BFactory.h:
#ifndef BFACTORY_H_
#define BFACTORY_H_
#include <exception>
class B
{
public:
virtual ~B(){}
virtual std::string whatAmI() = 0;
protected:
// data members common to all B subclasses
};
enum bType
{
gimmie_a_C,
gimmie_a_D,
gimmie_an_E
};
class BadTypeException: public std::exception
{
public:
const char* what() const noexcept
{
return "Dude! WTF?!?";
}
};
B* BFactory(enum bType type);
#endif /* BFACTORY_H_ */
Here I'm going to deviate from the book way a little. Rather than using an integer to identify the type to be built, I'm going to use an enum. Two reasons: Easier to read and understand gimme_a_C than 1 and generates a compiler error if you try to provide a value that is not enumerated.
enum bType
{
gimmie_a_C,
gimmie_a_D,
gimmie_an_E
};
And an exception to flag stupidity if the enum is updated with new types (gimmie_an_E) but the factory is not.
class BadTypeException: public std::exception
{
public:
const char* what() const noexcept
{
return "Dude! WTF?!?";
}
};
This is all the Factory client needs to see. They don't see C. They don't see D. They have no clue that C and D exist in any way other than the names listed in enum bType. All they ever see is pointers to B.
Now for the implementation BFactory.cpp:
#include "BFactory.h"
class C:public B
{
std::string whatAmI()
{
return "C";
}
};
class D:public B
{
std::string whatAmI()
{
return "D";
}
};
B* BFactory(enum bType type)
{
switch(type)
{
case gimmie_a_C:
return new C();
case gimmie_a_D:
return new C();
default:
throw BadTypeException();
}
}
I'll leave it up to the reader to spot the stupid bug in the above code that makes these error prone and why I don't like them.
And usage, main.cpp:
#include "BFactory.h"
int main()
{
B * temp;
temp = BFactory(gimmie_a_C);
std::cout << temp->whatAmI() << std::endl;
delete temp;
temp = BFactory(gimmie_a_D);
std::cout << temp->whatAmI() << std::endl;
delete temp;
//temp = BFactory(1001); // won't compile
try
{
temp = BFactory(gimmie_an_E); // will compile, throws exception
std::cout << temp->whatAmI() << std::endl;
}
catch(BadTypeException& wtf)
{
std::cerr << wtf.what() << std::endl;
}
}
There is still absolutely no use for or involvement of A. A if it exists, should no nothing about B or the children of B.
These days there is a little improvement we can make so that the pointers are a little safer. unique_ptr allows us to maintain the polymporphic advantages of a pointer to B without the memory management woes.
std::unique_ptr<B> BFactory(enum bType type)
{
switch(type)
{
case gimmie_a_C:
return std::unique_ptr<B>(new C());
case gimmie_a_D:
return std::unique_ptr<B>(new D());
default:
throw BadTypeException();
}
}
and the new main:
int main()
{
std::unique_ptr<B> temp;
temp = BFactory(gimmie_a_C);
std::cout << temp->whatAmI() << std::endl;
temp = BFactory(gimmie_a_D);
std::cout << temp->whatAmI() << std::endl;
}
You might want to define a constructor that takes the base class instance as the argument so you can later use static_cast to convert from the base class to the derived class.
class Derived : public Base
{
public:
Derived(const Base& base) : Base{base} {}
};
int main()
{
Base a;
Derived b = static_cast<Derived>(a);
}
If you want to create a derived class instance using the base class instance then there is some conversion rule between the two, which you can specify explicitly using a derived class constructor.
Although it is impossible to alter the type of an object you still can make instances of base and derived classes share the same data:
#include <memory>
#include <iostream>
class Base
{
protected:
struct CommonData
{
int A;
int B;
};
std::shared_ptr<CommonData> m_data;
public:
Base() : m_data(std::make_shared<CommonData>())
{
m_data->A = 0;
m_data->B = 0;
}
void SetData(Base * source)
{
m_data = source->m_data;
}
int A() const { return m_data->A; }
int B() const { return m_data->B; }
void SetA(int value) { m_data->A = value; }
void SetB(int value) { m_data->B = value; }
};
class Derived : public Base
{
public:
int C;
};
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Base base;
base.SetA(12);
base.SetB(46);
Derived derived;
derived.SetData(&base);
derived.C = 555;
cout << derived.A() << endl; // 12
cout << derived.C << endl; // 555;
cin.get();
}
A base class should not "know" about how to make its own derived class instances. That is the point of inheritance.
The "is a" relationship of derived classes means that any subclass instance will pass as a base class instance transparently, and you can treat it as one, and by default base class non-virtual methods are called on a base class reference, even if it a derived class instance. Only virtual methods use the derived class method.
In the case of creating a base class instance from a derived class you want to "slice" the instance data (normally a bad thing and normally a mistake).
class A{ // ... A stuff };
class B : A
{ // ... B stuff
A make_A() { return (A) B(*this); } // copy cast to A
};
Under no circumstances try to do this:
class B;
class A { // ...
B make_B() { return B(*this); }
};
That is inverted OO logic. It requires at least 2 scans of the source code, which C++ does not do. It fails.

Whose responsibility is it to delete

In C++, whose responsibility is it to delete members of a class: the class, or the creator of an instance of that class?
For example, in the following code:
class B {
public:
B(int x) { num = x; }
int num;
};
class A {
public:
A(B* o) { obj = o; }
B* obj;
};
int main(void) {
A myA(new B(3));
return 0;
}
Should main delete the instance of B, or should A's destructor delete its local variable obj? Is this true in most cases, and in which cases if any is it not?
This is a basic question of ownership. If every A should own a B (as in, there should be a new B created when the A is created, that should also be destroyed be the A is destroyed, then you'd normally make A responsible for creating and destroying the instance of B:
class B {
int num;
public:
B(int x) : num(x) {}
};
class A {
B *obj;
public:
A(int value) : obj(new B(value)) {}
~A() { delete B; }
};
In such a case, however, chances are pretty good that A should just be written like:
class A {
B obj;
public:
A(int v) : obj(v) {}
};
int main() {
A a(3);
return 0;
}
This way, the instance of B will be created and destroyed automatically, without any intervention on your part at all.
Almost always A should manage it's members as this is what RAII is based off of. Use unique_ptr when you can.
If it doesn't manage it's data then it should use a different smart pointer, specifically shared_ptr. This shifts the responsibility to the shared_ptr, which is much less error prone than a vanilla pointer.
And of course, the preferred way is to use no pointers at all. Why are you calling new in the first place?