A question about class object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Foo{
    public:
    Foo(){
        cout << "Foo()" << endl;
    }
    ~Foo(){
        cout << "~Foo()" << endl;
    }
};

class Ham :public Foo{
    public:
    Ham(){
        cout << "Ham()" << endl;
    }
    ~Ham(){
        cout << "~Ham()" << endl;
    }
};


int main(){
    Foo *foo = new Ham;
    delete foo;

    return 0;
}



Why do you use Foo class to make new Ham class? Why is this even working?

also, when you make pointer variable, you assign your pointer variable to your another variable address. But when you make pointer class, why do you not assign your pointer to address?

ex.
 
MyClass *myclass = new MyClass;


why not
MyClass *myclass = new &MyClass;
Last edited on
Its called inheritance (class Ham :Foo) and Polymorphism ( Foo *foo = new Ham;). And you probably want it to be.


class Ham : public Foo{ // added public

You can read all about it here-

Poly : https://www.google.se/#q=polymorphism+c%2B%2B

Inheritance : https://www.google.se/#q=inheritance+c%2B%2B

You'll also get a ton of results on youtube if you like to watch videos of people explaining them :)
Last edited on
But why this?

 
Foo *foo = new Ham;


this is same as saying,

 
int *Foo = new char;


Why would you use int to make a new char?


shouldn't the pointer pointing to address?

 
Foo *foo = new &ham;
No, it is not the same. Since Ham is derived from Foo, you can store Ham* in Foo* due to polymorphism. Remember that inheritance is an "is-a" relationship in C++, so by deriving Ham from Foo you are saying that a Ham "is-a" Foo and thus can be used wherever a Foo can be used.

Also, new already creates a pointer:
new Ham; //this returns a Ham*

new &Ham; //this makes no sense
Last edited on
Foo is the parent/base class. All classes that inherent from it are the sub/children classes. Ham in this case is the children class.

When you do this - [code]Foo *foo = new Ham;
Its the same as doing -

1
2
3
Ham object1;

Foo *foo = &object1;


Now, foo is pointing at an object of the class Ham, and can access hams functions
If in the ham class, you had a function void attack(){ }

foo->attack();
Last edited on
I think I got it but

Foo *foo = new Ham;

stores in heap and

1
2
Ham obj;
Foo *foo = &obj;


stores in stack, right?
Yes.

Foo *foo = new Ham;

You're allocating memory here, so it is placed in the heap.

Dont forget to learn about these things. They're important and useful in c++.
Now, foo is pointing at an object of the class Ham, and can access hams functions
If in the ham class, you had a function void attack(){ }

foo->attack();


This is not correct. You can only access Foo functions from a Foo*, even it actually is pointing to a Ham, because it might also be pointing to a Foo or a Bar, which probably won't have those functions.
Holy Moly maceroni and cheese you're right. I completely messed up how it works in my head :D

Edit: Yep, apparently I had forgotten how poly works...

It works something like this -

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Foo{
public:
	
	virtual void attack(){ }
};

class Ham :public Foo{
public:
	
	void attack(){ cout << "yo" << endl; }
};


int main(){
	
	Foo *foo = new Ham;
	foo->attack(); // this will call the attack function in Ham.
	
	system("pause");
	return 0;
}


Since void attack() is virtual inside of the parent class. It allows us to do Foo

1
2
Foo *foo = new Ham;
foo->attack();


Basically Because. foo is pointing at a Ham like @firedraco said. So when you do
foo->attack() it will go to the attack function inside of Foo. Then it will see that its virtual and say "oh shit wrong function" Then it will go and see where foo is pointing at, which is Ham. So it will go into ham, look for the attack() function there and call that one instead. (I hope I didint get anything too terribly wrong this time lol)

I think Video 52, 55, 56 and 57 explains this at the very basic level pretty well -

https://www.youtube.com/watch?v=tvC1WCdV1XU&list=PLAE85DE8440AA6B83&ab_channel=thenewboston
Last edited on
But why this?

Foo *foo = new Ham;

this is same as saying,

int *Foo = new char;


Nah, not quite.
They are both datatypes and you can convert an int to a char but an int is not a char and a char is not an int, that's the difference between that and polymorphiosm.
However, you could use a void* to point to either int or char
Note that you need to convert the void* to a char* or int* to access the data
1
2
3
4
5
6
7
8
9
10
11
int main(void)
{
	int a = 500;
	char b = 65;
	void* c = &b;
	std::cout << *(char*)c << std::endl;

	c = &a;
	std::cout << *(int*)c << std::endl;
	return 0;
}
I'll come back to that later

If you still wonder about that I'll give you the basics of polymorphism.
Imagine you have a TransportationObject. Yes, it's a transportation object, I couldn't think of a better name.
You might think about a Car or a Bike by now...
And yeah, both of them are TransportationObjects! :D

So without Polymorphism you might do something like this:
Imagine you have 2 different Obejcts which serve the same purpose (here you travel with them)
You choose 1 of them, but you'd do the same for every object.
switch/case looks good right?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class TransportationObject
{
public:
	virtual void travel() const
	{
		std::cout << "transportation:" << std::endl;
	}
};
class Car : public TransportationObject
{
public:
	virtual void travel() const { std::cout << "transportation: Car" << std::endl; }
};
class Bike: public TransportationObject
{
public:
	virtual void travel() const { std::cout << "transportation: Bike" << std::endl; }
};

int main(void)
{
	srand (time(NULL)); // for finding best choise
	Car car;
	Bike bike;

	switch(rand() % 2)
	{
        // same algorithm twice
		case 0: for(int i = 0; i < 100; ++i) car.travel(); break;
		case 1: for(int i = 0; i < 100; ++i) bike.travel(); break; 
		default: break;
	}
}
Yeah... it works
But you have the same algorithm for both cases so isn't there a better way?
Yes. the answer is, simple, use polymorphism, "when a class derives public from an other class the Derived class has a is-an-relation with the base class" (no quote)
That means a Car is a Transportation Object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class TransportationObject
{
public:
	virtual void travel() const
	{
		std::cout << "transportation:" << std::endl;
	}
};
class Car : public TransportationObject
{
public:
	virtual void travel() const { std::cout << "transportation: Car" << std::endl; }
};
class Bike: public TransportationObject
{
public:
	virtual void travel() const { std::cout << "transportation: Bike" << std::endl; }
};


Now you have a Car and a Bike at home.
You don't know what you want to take so you... yeah... try to find out.
After finding out, you want to travel, maybe 100 times to different places?
Keep in mind, that Car and Bike are both TransportationObjects (public inheritance)
So logically speaking, you choose between 2 similar Objects.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
TransportationObject* find_best_choise(TransportationObject* o1,TransportationObject* o2)
{
	switch(rand() % 2)
        {
            case 0: return o1;
            case 1: return o2;
            default: return nullptr;
        }
}

int main(void)
{
  srand (time(NULL)); // for finding best choise
	Car car;
	Bike bike;

	TransportationObject* object = find_best_choise(&car, &bike);

// Now do something with the desired Object
        for(int i = 0; i < 100; ++i) 
	    object->travel();
}

You see, here you get the Object you want to work with and after that you don't care about that anymore.

To get back to the void* example, imagine Car has a Method called refill, and when traveling you want to refill your Car, but you don't need to refill your bike
in that case you have to cast it to the derived class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
enum { ID_GENERAL, ID_CAR, ID_BIKE };
class TransportationObject
{
public:
        TransportationObject() : id(ID_GENERAL) {}
        int id;
	virtual void travel() const
	{
		std::cout << "transportation:" << std::endl;
	}
};
class Car : public TransportationObject
{
public:
        Car() : id(ID_CAR) {}
	virtual void travel() const { std::cout << "transportation: Car" << std::endl; }
        void refill() const { std::cout << "Car: refill" << std::endl; }
};
class Bike: public TransportationObject
{
public:
        Bike() : id(ID_BIKE) {}
	virtual void travel() const { std::cout << "transportation: Bike" << std::endl; }
};

int main(void)
{
  srand (time(NULL)); // for finding best choise
	Car car;
	Bike bike;

	TransportationObject* object = find_best_choise(&car, &bike);

// Now do something with the desired Object
        for(int i = 0; i < 100; ++i) 
	{
// things you do with all objects
            object->travel();

// things you do with spezific types
            if(object->id == ID_CAR)
                ((Car*)(object))->refill();
        }
}




I hope this post is easy to understand.
Last edited on
Topic archived. No new replies allowed.