"With great power comes great responsibility" -popularized in Spider-Man Well, here you are provided with virtually limitless possibility to do whatever you want and with freedom you have -- in return you need to handle it all by yourself.
I cannot emphasize how important a subject this is. One of the harder things to debug in C++ is when you think a destructor is being called, but is not because it was not virtual. This is a serious programming error that must be avoided by following this rule: always make destructors virtual with one exception. If the class is a base class (not derived), you don't ever expect to derive from it, and you put the comment "// non-virtual object!" right above the class definition, then the destructor can be non-virtual. If you ever want to derive from it you will see the comment indicating you need to add virtual to the base destructor.
hey man, you are the reason why I started coding you make it look simple and interesting. your videos are like suspense movies, I just wanna watch more and more.
Hi man, I think you are such a crusher in C++. I did a C++ course called Advanced C++ programming at my Uni few years ago, but I couldn't link the knowledge together back in the day. After watching your video series, things start making sense to me now.
Can you make video about (virtual inheritance, diamond problem, multiple inheritance) ? How to use it and how it works? You are making good job and talking about difficult things very clearly. Greetings to You.
A good tip is that you can always declare your class' destructors as virtual. This doesn't have any adverse effect for a class that does not have any child classes, but it will help if there are classes in the future that have to be derived from a base. Also worth mentioning that the Base class' virtual destructor will carry over regardless of the number of generations that are created(Parent class becomes a Grandparent, so-to-speak, or Great-Grandparent, so on..): The children and grandchildren all will still have their own respective destructors called as long as, at the very least, the 1st generation has a virtual destructor.
When a derived class calls its constructor does the compiler implicitly call the base class constructor as well? In the example after calling the constructor of derived class it seemed to call the base class constructor first even when the destuctor of the base class was called in a statement before.
Just an FYI, the location of the video cards (suggesting to jump to previous videos you made) is on the right for people using LTR language on TH-cam (like English), and on the left for people using RTL (like Arabic)
As far as I know, The classes that have "virtual" (any virtual keyword) will need a pointer to point to a vtable. It costs 1 vtable each class and a pointer for each instance. You can try sizeof(ClassHasVirtual) and sizeof(ClassDoesntHaveVirtual) to see the different. Sorry for my bad English. It's just an idea. You can google for more information.
How about this: you could cast your pointer to the derived class and call the derived class destructor if you really want to save on memory used by vtables. Any comments?
The vtable not only requires an extra pointer but has a (very small) amount of overhead to look the correct function version up. Actually, commonly accepted best practices will say to always make the destructor virtual (and some IDEs will warn you if you don't). But C++ likes to give you power to choose as you like -- so, say, a small vec3f class (or a struct) might not need one *if* you know you will never extend it. C++ leave the option, just in case (unlike, say, Java, where all methods are inherently virtual).
Henri de Feraudy: The problem is that, is many applications, the type will be determined at run time, and you won't always know what type it is before hand. Also, there is the danger you might foreget, or someone else will work on the code. For example, you create a type entity, and derived types zombie and skeleton, with different data. You store all the current entities in a game in a vector as the spawn. When they despawn they are removed from the vector and the destructor is called. A loop that runs on all entities in a the vector doesn't know if a given entity is a skeleton or a zombie.
Quick question though, why would you create a pointer to the base class but then make it point to the memory address of a derived class? Seems to me like you can avoid the problem if you simply create the appropriate pointer to begin with. Is there another reason why'd you'd want to use a base class pointer to point to a derived class?
For instances where you don't necessarily know if it is Base or Derived. For example, if you have an entity class with a move method, with a derived player class, you might want all entities in the scene to update inside of a loop. So you might create an array of entities and assign one of the positions of the array to the player, as an example
great content! how these concepts are shifted into the smart pointers? I actually got that smart pointers, delete objects by themself when program doesn't need anymore.
If we have 3 classes A,B,C. A is the master class, B inherits from A and C inherits from B. The only Virtual Constructor Is A’s. If I treat a C instance as an A instance all three constructors are called or only A, B? And a second question if I treat the C instance as a B instance only the B constructor is called right?
I am not 100% sure I understood you correctly, but constructors are always called in the hierarchical "tree" of inheritance. I do not hink there is something like a virtual constructor, there are only virtual destructors. In both cases the 3 constructs will be called in the order: A,B,C. In your second example, all 3 are called again, since B inherits from A. Nonetheless you can always try it
I just tested it out and in both cases all 3 constructors and all 3 destructors were called, whereas I declared only the destructor of A as virtual. If you think about it , it makes sense, because virtual basically means that the method can be overridden. So the B destructor calls the destructor of A. Since the object is of type C it must go up the tree through B and then to A, which in a sense "overrides" B's destructor which overrides A's destructor because it was declared virtual. But better check the c++ documentation or ask someone more sophisticated
When using std::shared_ptr poly = std::make_shared(), my program called BOTH the derived AND base destructor when exiting the scope even though I hadn't marked ~Base() as virtual (windows 7, mingw compiler). Is it something shared_pointer does, is it something that make_shared does, or is it something I completely missed?
what does base* poly = new derived mean? why ever does this? from my understanding the base tells the compiler how much memory is required. but since derived calsses will have more variable and stuff than base, this will result in the pointer base having more memory than what it thinks is required. i hope that made sense. like assume base has 1 int which is 4 bytes thus a point to base will have 4 bytes at the address of base. if i say base pointer and give it a pointer of a derived now it still thinks that it has 4 bytes but the derived might have 2 ints and thus 8 bytes.
@Peterolen thank you for this, this helped med in understanding. i now understand that the base class can store the pointers to the deriaved classes but you have to be very cafull and know what each deriaved class is. Else you would confuse the deriaved classes and if u assume that the class a is what u are hold the pointer to but in reality it is class but then upon calling a class a memeber or function class b would return and error as they dont exist and the program would crash.
Yes. class Base { public: Base(int bla) : m_bla(bla) {} private: int m_bla: }; class Derived : public Base { public: Derived() : Base(5) {} }; Note: The Base constructor must be called in the member initialization list. Calling Base in the constructor body does nothing except create a Base instance which gets destroyed at the end of the scope.
"Whenever your writing a class that you will be extending or that might be sub-classed you need to declare your destructor as 'virtual' otherwise no one is going to be able to safely extend that class including yourself because if you do that you can't use the destructor because it will never get called if you're treating that class by it's base type which might be the case if your passing it into a function as well and maybe that function only takes it as a base pointer and then deletes it or does whatever it does. This is an example anyway so definitely make sure that you are declaring the destructors 'virtual' if your allowing that sub-class to actually happen." - Cherno
TheChernoProject, could you please tell me how you make game engines in EA, I think you said you made them in C#. How? I can't find many good ways to write a game enigine in C#. in fact this is why im learning C++.
Yes, but how would I get a screen and render it in C#? I mean these all kinds of SDL SFML and the list goes on for C++. but C#? I cant find nothing like that in C#.
I'd recommend not using the term "sub-class" because it's not a part of the specification and creates ambiguity between *derived classes* and *nested classes.*
Hey cherno can you do help me understand the tile coordinate system from game programming episode 62? I understand the x and y used in the constructor but not the r function and the tile size parameter. Can you please explain in depth how to use them? I am wanting to use them in a platformer type game but I want to understand really what they do better. Also the game I am trying to develop uses 4by4, 8by8, 16by16, and 32by32 tiles respectively. Unfortunately the way the program that you built runs only operates on 16by16 tiles. I want a different one that can operate on any type of sprite size no matter what I throw into it.
Imagine if the base class need's to do some memory allocation's or setup some stuff, before it can be utilized, that's why base constructor is called First
Not for classes that will never be subclassed, since you don't want to add the overhead of a vtable if you don't need to. If you ever have any virtual functions in your class then yes, always. Note that you of course do not need to have virtual functions to require a virtual destructor, since virtual desctructors should be used on every class that is subclassed.
I hate OOP 😭, dunno what im gonna DO... IT'S HARD IT'S HARD IT'S HARD . It doesn't make sense it should not exists It's ruining everything in my life😭😭😭
Where were you in the 90s when I was teaching myself C++? Back them this was very difficult to figure out. XLNT video.
He was learning to talk
He hasnt born yet.
hi unc
I don't even burn bro 😭🙏
My final is due tomorrow. This video has been a great help. Infact the whole series on C++ is marvellous!
Been programming for years never knew this. Thx man.
damn, so much potential for memory leaks..
We can use sharedptr pr uniquedptr to avoid memory leak.
"With great power comes great responsibility" -popularized in Spider-Man
Well, here you are provided with virtually limitless possibility to do whatever you want and with freedom you have -- in return you need to handle it all by yourself.
@@huunoidoan Well, if you have 2 shared pointers and a circular dependency between both you can also have a memory leak.
I cannot emphasize how important a subject this is. One of the harder things to debug in C++ is when you think a destructor is being called, but is not because it was not virtual. This is a serious programming error that must be avoided by following this rule: always make destructors virtual with one exception. If the class is a base class (not derived), you don't ever expect to derive from it, and you put the comment "// non-virtual object!" right above the class definition, then the destructor can be non-virtual. If you ever want to derive from it you will see the comment indicating you need to add virtual to the base destructor.
hey man, you are the reason why I started coding you make it look simple and interesting. your videos are like suspense movies, I just wanna watch more and more.
Hi man, I think you are such a crusher in C++. I did a C++ course called Advanced C++ programming at my Uni few years ago, but I couldn't link the knowledge together back in the day. After watching your video series, things start making sense to me now.
That's why i decide to become on a partner supporter on Patreon
Hey is there any reason Cherno hasn't uploaded in more than 10 days? :(
I have no idea
Can you make video about (virtual inheritance, diamond problem, multiple inheritance) ? How to use it and how it works?
You are making good job and talking about difficult things very clearly.
Greetings to You.
I used to see Virtual inheritance solve multi inheritance
Piotr S Multiple inheritance isn't usually a good idea, just FYI.
yes, i heared about it, but i just want to now how it works in background, because it is an element of language and good to know that.
Can't believe you actually have a video on this topic! Thought I was headed for some head-scratching on cppreference (which ain't even a bad site).
Duuddeeeee GOD BLESS YOU! It was SOOO easy to understand OMG!
2022. This stuff never gets old. Thanks Cherno!
All these C++ "features" that programmers need to learn, seem more like C++ bugs that we need to patch lol
Exception handling good/bad and how you deal with errors would be a fantastic video! :) pls :)
This is just what I would like to see next. Magic.
this was REALLY GOOD. thank you.
Great to know - thanks!
Nice video!
Keep up the good work!
How come I've never come across this before? Thank you so much. This was great.
Lol @ the subtitles here: "Hey look guys my name is Jenna..."
Thank you so much for your amazing videos!
are you planning to do videos on data structures and algorithms ??
Simple. I get it now. Thanks Cherno.
A good tip is that you can always declare your class' destructors as virtual.
This doesn't have any adverse effect for a class that does not have any child classes, but it will help if there are classes in the future that have to be derived from a base.
Also worth mentioning that the Base class' virtual destructor will carry over regardless of the number of generations that are created(Parent class becomes a Grandparent, so-to-speak, or Great-Grandparent, so on..): The children and grandchildren all will still have their own respective destructors called as long as, at the very least, the 1st generation has a virtual destructor.
Can u code in c++ now?
How is the memory cost? As far as I know, a virtual function will incur a virtual pointer.
My man!! Thank you :-)
7:01 why this is already build in compiler?
Nice video and extremely useful to know!!!
Hi. Will there be a series with creating a game engine with your great explanations?) Thanks
When a derived class calls its constructor does the compiler implicitly call the base class constructor as well?
In the example after calling the constructor of derived class it seemed to call the base class constructor first even when the destuctor of the base class was called in a statement before.
Why the base constructor does not need to be virtual?
You said previously that you work at EA on core technology I'm curious what engine are you actively developing. Frostbite?
He works on EA in Australia(Firemonkeys Studios) so it is not Frostbite (since that is made by DICE in Sweden)
Mobile engine
Just an FYI, the location of the video cards (suggesting to jump to previous videos you made) is on the right for people using LTR language on TH-cam (like English), and on the left for people using RTL (like Arabic)
thanks
why to use x * y = new y() instead of x y()?
+1
@@chiyungchu9463 hey man,can you code in c++?
Can I also make the derived class destructor virtual?
I am very confused how vptr and vtable works. Please make a video on that too.
This series is excellent! Does anybody know what the performance cost is of declaring destructors as virtual?
Why would we then not use virtual destructors every time? Why isn't this the default ?
As far as I know, The classes that have "virtual" (any virtual keyword) will need a pointer to point to a vtable. It costs 1 vtable each class and a pointer for each instance.
You can try sizeof(ClassHasVirtual) and sizeof(ClassDoesntHaveVirtual) to see the different.
Sorry for my bad English. It's just an idea. You can google for more information.
c++ babe!!!
How about this: you could cast your pointer to the derived class and call the derived class destructor if you really want to save on memory used by vtables. Any comments?
The vtable not only requires an extra pointer but has a (very small) amount of overhead to look the correct function version up. Actually, commonly accepted best practices will say to always make the destructor virtual (and some IDEs will warn you if you don't). But C++ likes to give you power to choose as you like -- so, say, a small vec3f class (or a struct) might not need one *if* you know you will never extend it. C++ leave the option, just in case (unlike, say, Java, where all methods are inherently virtual).
Henri de Feraudy: The problem is that, is many applications, the type will be determined at run time, and you won't always know what type it is before hand. Also, there is the danger you might foreget, or someone else will work on the code.
For example, you create a type entity, and derived types zombie and skeleton, with different data. You store all the current entities in a game in a vector as the spawn. When they despawn they are removed from the vector and the destructor is called. A loop that runs on all entities in a the vector doesn't know if a given entity is a skeleton or a zombie.
Thanks!
He is talking right. Give him beer
when you need to do something like that Base* poly = new Derived();? why you you need instance of Base that is created with Derived?
Hey Cherno, we are waiting for static polymorphism video
i never knew this could happen
why treat sub class pointer as base class pointer?
what happens if we use pure virtual destructor?
Can someone please explain why we have to put a "public" after the ":"?
@Peterolen wow, okay. I can't really find any usecase for such a privately inheriting class though
what happens if you put the virtual on the derived destructor?
I feel like this is the first time we touched deleting classes in all the class videos. Why so? When and when not to?
Thsnks
Awesome
Quick question though, why would you create a pointer to the base class but then make it point to the memory address of a derived class? Seems to me like you can avoid the problem if you simply create the appropriate pointer to begin with. Is there another reason why'd you'd want to use a base class pointer to point to a derived class?
For instances where you don't necessarily know if it is Base or Derived. For example, if you have an entity class with a move method, with a derived player class, you might want all entities in the scene to update inside of a loop. So you might create an array of entities and assign one of the positions of the array to the player, as an example
great content! how these concepts are shifted into the smart pointers? I actually got that smart pointers, delete objects by themself when program doesn't need anymore.
Can we expect a video on detailed explanation on VTable and Vptr from you soon, pls.
Why we don't need virtual constructor though? Might be a dumb question, but thanks for any reply.
what is the use of pure virtual function?
If we have 3 classes A,B,C. A is the master class, B inherits from A and C inherits from B. The only Virtual Constructor Is A’s. If I treat a C instance as an A instance all three constructors are called or only A, B? And a second question if I treat the C instance as a B instance only the B constructor is called right?
I am not 100% sure I understood you correctly, but constructors are always called in the hierarchical "tree" of inheritance. I do not hink there is something like a virtual constructor, there are only virtual destructors. In both cases the 3 constructs will be called in the order: A,B,C. In your second example, all 3 are called again, since B inherits from A. Nonetheless you can always try it
Oh my mistake I was talking about destructors not constructors
Valiok 98 I meant virtual destructors
I just tested it out and in both cases all 3 constructors and all 3 destructors were called, whereas I declared only the destructor of A as virtual. If you think about it , it makes sense, because virtual basically means that the method can be overridden. So the B destructor calls the destructor of A. Since the object is of type C it must go up the tree through B and then to A, which in a sense "overrides" B's destructor which overrides A's destructor because it was declared virtual. But better check the c++ documentation or ask someone more sophisticated
Valiok 98 Thanks ever so much
When using std::shared_ptr poly = std::make_shared(), my program called BOTH the derived AND base destructor when exiting the scope even though I hadn't marked ~Base() as virtual (windows 7, mingw compiler). Is it something shared_pointer does, is it something that make_shared does, or is it something I completely missed?
thanks a lot sir
what does base* poly = new derived mean?
why ever does this?
from my understanding the base tells the compiler how much memory is required.
but since derived calsses will have more variable and stuff than base, this will result in the pointer base having more memory than what it thinks is required.
i hope that made sense. like assume base has 1 int which is 4 bytes thus a point to base will have 4 bytes at the address of base. if i say base pointer and give it a pointer of a derived now it still thinks that it has 4 bytes but the derived might have 2 ints and thus 8 bytes.
@Peterolen thank you for this, this helped med in understanding.
i now understand that the base class can store the pointers to the deriaved classes but you have to be very cafull and know what each deriaved class is.
Else you would confuse the deriaved classes and if u assume that the class a is what u are hold the pointer to but in reality it is class but then upon calling a class a memeber or function class b would return and error as they dont exist and the program would crash.
If u could make a video on types of bugs that can be present, that you have seen, that would be great. Run time bugs, I mean.
For example, right now my PNF_Object2 crashes sometime when I create an object of that type. Thats what I'm working on right now.
Wow, I have neve realized how many memory leaks i made lol
I'm not joking but Yan looks like Chris Pratt
nice video cherno , i have a question : can we call the superclass constructor from base class like in java super.(); thanks for the video.
Yes.
class Base {
public:
Base(int bla) : m_bla(bla) {}
private:
int m_bla:
};
class Derived : public Base {
public:
Derived() : Base(5) {}
};
Note: The Base constructor must be called in the member initialization list. Calling Base in the constructor body does nothing except create a Base instance which gets destroyed at the end of the scope.
2:05 :(on Line 10)
"lass Derived : public Base"
Question: Why do we need specify "public" for base class? Any reason?
Great explanation! thank you
This guy types so FAST
Can you make a video about linked lists or binary trees? By the way keep up the good work, you're very good at this!
What IDE do you use? it looks like something I'd want to try out.
King Luke it’s visual studio
Visual Studio
Oh haha, thanks guys!
Why can't the compiler warn you when you are inheriting from a class without a virtual destructor?
cool
"Whenever your writing a class that you will be extending or that might be sub-classed you need to declare your destructor as 'virtual' otherwise no one is going to be able to safely extend that class including yourself because if you do that you can't use the destructor because it will never get called if you're treating that class by it's base type which might be the case if your passing it into a function as well and maybe that function only takes it as a base pointer and then deletes it or does whatever it does. This is an example anyway so definitely make sure that you are declaring the destructors 'virtual' if your allowing that sub-class to actually happen." - Cherno
you're*
I am new to C++ and OOPS, can somebody please explain what is the use case of when you do:
Base* poly = new Derived();
TheChernoProject, could you please tell me how you make game engines in EA, I think you said you made them in C#. How? I can't find many good ways to write a game enigine in C#. in fact this is why im learning C++.
The core engine is made in c++ and the tools used in engine is made with c#
Yes, but how would I get a screen and render it in C#? I mean these all kinds of SDL SFML and the list goes on for C++. but C#? I cant find nothing like that in C#.
Thank you for your response. that makes a lot of sense now.
Thanks for telling me what should be in an engine! i kind of needed that
I'd recommend not using the term "sub-class" because it's not a part of the specification and creates ambiguity between *derived classes* and *nested classes.*
what is the software/hardware you use to record these tutorials :)
You can see that he is aging if you compare him with the first video
Hey cherno can you do help me understand the tile coordinate system from game programming episode 62? I understand the x and y used in the constructor but not the r function and the tile size parameter. Can you please explain in depth how to use them? I am wanting to use them in a platformer type game but I want to understand really what they do better. Also the game I am trying to develop uses 4by4, 8by8, 16by16, and 32by32 tiles respectively. Unfortunately the way the program that you built runs only operates on 16by16 tiles. I want a different one that can operate on any type of sprite size no matter what I throw into it.
Help, i have a function in a class:
class Logging {
public:
void Log(const char* text) {
std::cout
What if i wanted to do Log("FPS: " + fps); // Fps doesnt exist but just an example
thanks
I don't really understand why the base constructor is called when a derived object is constructed. Can someone ELI5?
Imagine if the base class need's to do some memory allocation's or setup some stuff, before it can be utilized, that's why base constructor is called First
Thank you.
why is 'virtual' not the default state like it is in other languages?
Because it adds overhead on both the cpu and memory.
uff more leaks
]
when will the Game Engine Tutorial series began ??
So, should I make every destructor virtual just to be safe?
Not for classes that will never be subclassed, since you don't want to add the overhead of a vtable if you don't need to. If you ever have any virtual functions in your class then yes, always. Note that you of course do not need to have virtual functions to require a virtual destructor, since virtual desctructors should be used on every class that is subclassed.
How much time did you need to learn C++ and Java...(You are programming for 7 Years but how much Time did you need to learn this two Languages ?)
Second comment:
Representing Second place... The first loser.. I like your style. Keep up the good work.
I hate OOP 😭, dunno what im gonna DO... IT'S HARD IT'S HARD IT'S HARD .
It doesn't make sense it should not exists It's ruining everything in my life😭😭😭
How much time did you need to learn C++ and Java...(You are programming for 7 Years but how much Time did you need to learn this two Languages ?)