Virtual Destructors in C++

แชร์
ฝัง
  • เผยแพร่เมื่อ 14 ธ.ค. 2024

ความคิดเห็น • 141

  • @johnpawlicki1184
    @johnpawlicki1184 6 ปีที่แล้ว +103

    Where were you in the 90s when I was teaching myself C++? Back them this was very difficult to figure out. XLNT video.

    • @cajogos
      @cajogos 5 ปีที่แล้ว +71

      He was learning to talk

    • @chiyungchu9463
      @chiyungchu9463 3 ปีที่แล้ว +4

      He hasnt born yet.

    • @pastori2672
      @pastori2672 6 หลายเดือนก่อน

      hi unc

    • @BobChess
      @BobChess 3 หลายเดือนก่อน

      I don't even burn bro 😭🙏

  • @SuperKhezar
    @SuperKhezar 6 ปีที่แล้ว +58

    My final is due tomorrow. This video has been a great help. Infact the whole series on C++ is marvellous!

  • @MudHoleCreation
    @MudHoleCreation 6 ปีที่แล้ว +55

    Been programming for years never knew this. Thx man.

  • @rcookie5128
    @rcookie5128 6 ปีที่แล้ว +90

    damn, so much potential for memory leaks..

    • @huunoidoan
      @huunoidoan 6 ปีที่แล้ว +5

      We can use sharedptr pr uniquedptr to avoid memory leak.

    • @aldeywahyuputra5719
      @aldeywahyuputra5719 4 ปีที่แล้ว +7

      "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.

    • @c0ldw1nd27
      @c0ldw1nd27 4 ปีที่แล้ว +2

      @@huunoidoan Well, if you have 2 shared pointers and a circular dependency between both you can also have a memory leak.

  • @drwisdom1
    @drwisdom1 5 ปีที่แล้ว +17

    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.

  • @pratiktata3388
    @pratiktata3388 6 ปีที่แล้ว +19

    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.

  • @fufuhu148
    @fufuhu148 6 ปีที่แล้ว +3

    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.

    • @fufuhu148
      @fufuhu148 6 ปีที่แล้ว +1

      That's why i decide to become on a partner supporter on Patreon

    • @pooria_garrett3020
      @pooria_garrett3020 6 ปีที่แล้ว

      Hey is there any reason Cherno hasn't uploaded in more than 10 days? :(

    • @fufuhu148
      @fufuhu148 6 ปีที่แล้ว +1

      I have no idea

  • @piotrs7632
    @piotrs7632 6 ปีที่แล้ว +70

    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.

    • @huyvole9724
      @huyvole9724 6 ปีที่แล้ว

      I used to see Virtual inheritance solve multi inheritance

    • @dmitrimcguckin299
      @dmitrimcguckin299 6 ปีที่แล้ว +4

      Piotr S Multiple inheritance isn't usually a good idea, just FYI.

    • @piotrs7632
      @piotrs7632 6 ปีที่แล้ว +1

      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.

  • @josiahlamb
    @josiahlamb 4 ปีที่แล้ว +1

    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).

  • @inara9888
    @inara9888 6 ปีที่แล้ว +5

    Duuddeeeee GOD BLESS YOU! It was SOOO easy to understand OMG!

  • @a740g
    @a740g 2 ปีที่แล้ว

    2022. This stuff never gets old. Thanks Cherno!

  • @pfever
    @pfever 2 ปีที่แล้ว +1

    All these C++ "features" that programmers need to learn, seem more like C++ bugs that we need to patch lol

  • @Xxp0r
    @Xxp0r 6 ปีที่แล้ว +1

    Exception handling good/bad and how you deal with errors would be a fantastic video! :) pls :)

  • @dadlord689
    @dadlord689 6 ปีที่แล้ว

    This is just what I would like to see next. Magic.

  • @omkarpatil2094
    @omkarpatil2094 3 ปีที่แล้ว

    this was REALLY GOOD. thank you.

  • @mikeorioles
    @mikeorioles ปีที่แล้ว

    Great to know - thanks!

  • @fleckgames5261
    @fleckgames5261 6 ปีที่แล้ว

    Nice video!
    Keep up the good work!

  • @FuryOnStage
    @FuryOnStage 6 ปีที่แล้ว

    How come I've never come across this before? Thank you so much. This was great.

  • @Llonerin2
    @Llonerin2 5 ปีที่แล้ว +1

    Lol @ the subtitles here: "Hey look guys my name is Jenna..."

  • @Cc618.
    @Cc618. 6 ปีที่แล้ว

    Thank you so much for your amazing videos!

  • @rajakishan1
    @rajakishan1 5 ปีที่แล้ว +2

    are you planning to do videos on data structures and algorithms ??

  • @femloh
    @femloh 2 ปีที่แล้ว

    Simple. I get it now. Thanks Cherno.

  • @KingCitaldo125
    @KingCitaldo125 4 ปีที่แล้ว +8

    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.

    • @jurakpreetsingh2155
      @jurakpreetsingh2155 3 ปีที่แล้ว

      Can u code in c++ now?

    • @wang_7665
      @wang_7665 2 ปีที่แล้ว +1

      How is the memory cost? As far as I know, a virtual function will incur a virtual pointer.

  • @SusilRamarao
    @SusilRamarao 3 ปีที่แล้ว

    My man!! Thank you :-)

  • @maciej12345678
    @maciej12345678 3 ปีที่แล้ว

    7:01 why this is already build in compiler?

  • @nikoszervo
    @nikoszervo 6 ปีที่แล้ว

    Nice video and extremely useful to know!!!

  • @РустемСултанов-т5и
    @РустемСултанов-т5и 6 ปีที่แล้ว +4

    Hi. Will there be a series with creating a game engine with your great explanations?) Thanks

  • @varunduke
    @varunduke 3 ปีที่แล้ว +1

    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.

  • @jcfb9527
    @jcfb9527 4 ปีที่แล้ว +1

    Why the base constructor does not need to be virtual?

  • @rob-890
    @rob-890 6 ปีที่แล้ว +5

    You said previously that you work at EA on core technology I'm curious what engine are you actively developing. Frostbite?

    • @Keltheran
      @Keltheran 6 ปีที่แล้ว +4

      He works on EA in Australia(Firemonkeys Studios) so it is not Frostbite (since that is made by DICE in Sweden)

    • @zf0666
      @zf0666 6 ปีที่แล้ว +3

      Mobile engine

  • @yardencohen9521
    @yardencohen9521 3 ปีที่แล้ว

    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)

  • @tjalferes
    @tjalferes 2 ปีที่แล้ว

    thanks

  • @zielony1212
    @zielony1212 3 ปีที่แล้ว +2

    why to use x * y = new y() instead of x y()?

  • @SumanthLingappa
    @SumanthLingappa 2 หลายเดือนก่อน

    Can I also make the derived class destructor virtual?

  • @siddharthchauhan1129
    @siddharthchauhan1129 4 ปีที่แล้ว +1

    I am very confused how vptr and vtable works. Please make a video on that too.

  • @oceanexplorationlab
    @oceanexplorationlab ปีที่แล้ว +1

    This series is excellent! Does anybody know what the performance cost is of declaring destructors as virtual?

  • @ghipsandrew
    @ghipsandrew 6 ปีที่แล้ว +9

    Why would we then not use virtual destructors every time? Why isn't this the default ?

    • @loia5tqd001
      @loia5tqd001 6 ปีที่แล้ว +9

      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.

    • @nikoszervo
      @nikoszervo 6 ปีที่แล้ว +5

      c++ babe!!!

    • @feraudyh
      @feraudyh 6 ปีที่แล้ว

      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?

    • @BlackJar72
      @BlackJar72 6 ปีที่แล้ว +5

      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).

    • @BlackJar72
      @BlackJar72 6 ปีที่แล้ว +1

      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.

  • @eyalpery8470
    @eyalpery8470 4 ปีที่แล้ว

    Thanks!

  • @Nuclearblastdrone
    @Nuclearblastdrone 5 ปีที่แล้ว

    He is talking right. Give him beer

  • @vbessonow
    @vbessonow 3 ปีที่แล้ว

    when you need to do something like that Base* poly = new Derived();? why you you need instance of Base that is created with Derived?

  • @huseyinsencan8627
    @huseyinsencan8627 6 ปีที่แล้ว +1

    Hey Cherno, we are waiting for static polymorphism video

  • @l6e6i6n
    @l6e6i6n 4 ปีที่แล้ว

    i never knew this could happen

  • @LucyAndLily502
    @LucyAndLily502 11 หลายเดือนก่อน

    why treat sub class pointer as base class pointer?

  • @soumyadeepdas1199
    @soumyadeepdas1199 ปีที่แล้ว

    what happens if we use pure virtual destructor?

  • @peterarbeitsloser7819
    @peterarbeitsloser7819 3 ปีที่แล้ว

    Can someone please explain why we have to put a "public" after the ":"?

    • @peterarbeitsloser7819
      @peterarbeitsloser7819 3 ปีที่แล้ว

      @Peterolen wow, okay. I can't really find any usecase for such a privately inheriting class though

  • @julianelischer
    @julianelischer 5 ปีที่แล้ว

    what happens if you put the virtual on the derived destructor?

  • @Yupppi
    @Yupppi ปีที่แล้ว

    I feel like this is the first time we touched deleting classes in all the class videos. Why so? When and when not to?

  • @mallasarjsulebhanvi4128
    @mallasarjsulebhanvi4128 2 ปีที่แล้ว

    Thsnks

  • @abhisheksa6635
    @abhisheksa6635 ปีที่แล้ว

    Awesome

  • @eduardovaldez4013
    @eduardovaldez4013 2 ปีที่แล้ว

    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?

    • @guy-dev
      @guy-dev 2 ปีที่แล้ว

      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

  • @giusepperandazzo5357
    @giusepperandazzo5357 2 ปีที่แล้ว

    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.

  • @nandhakumarmurugan9923
    @nandhakumarmurugan9923 4 ปีที่แล้ว

    Can we expect a video on detailed explanation on VTable and Vptr from you soon, pls.

  • @UchihaNarutoFTW
    @UchihaNarutoFTW 7 หลายเดือนก่อน

    Why we don't need virtual constructor though? Might be a dumb question, but thanks for any reply.

  • @PuneetKumar-mz9is
    @PuneetKumar-mz9is 6 ปีที่แล้ว

    what is the use of pure virtual function?

  • @xristosbart8217
    @xristosbart8217 6 ปีที่แล้ว +3

    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?

    • @valiok9880
      @valiok9880 6 ปีที่แล้ว

      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

    • @xristosbart8217
      @xristosbart8217 6 ปีที่แล้ว +1

      Oh my mistake I was talking about destructors not constructors

    • @xristosbart8217
      @xristosbart8217 6 ปีที่แล้ว +1

      Valiok 98 I meant virtual destructors

    • @valiok9880
      @valiok9880 6 ปีที่แล้ว

      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

    • @xristosbart8217
      @xristosbart8217 6 ปีที่แล้ว

      Valiok 98 Thanks ever so much

  • @a2p75
    @a2p75 2 ปีที่แล้ว

    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?

  • @eshaanrathi4658
    @eshaanrathi4658 6 ปีที่แล้ว

    thanks a lot sir

  • @ajj7794
    @ajj7794 4 ปีที่แล้ว

    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.

    • @ajj7794
      @ajj7794 4 ปีที่แล้ว

      @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.

  • @smileynetsmileynet7922
    @smileynetsmileynet7922 4 ปีที่แล้ว +1

    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.

    • @smileynetsmileynet7922
      @smileynetsmileynet7922 4 ปีที่แล้ว +1

      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.

  • @k-tech2937
    @k-tech2937 3 ปีที่แล้ว

    Wow, I have neve realized how many memory leaks i made lol

  • @haxterhuz8346
    @haxterhuz8346 6 ปีที่แล้ว +18

    I'm not joking but Yan looks like Chris Pratt

  • @redon4
    @redon4 6 ปีที่แล้ว +2

    nice video cherno , i have a question : can we call the superclass constructor from base class like in java super.(); thanks for the video.

    • @jamesmnguyen
      @jamesmnguyen 6 ปีที่แล้ว +4

      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.

  • @GfastGao
    @GfastGao 6 ปีที่แล้ว

    2:05 :(on Line 10)
    "lass Derived : public Base"
    Question: Why do we need specify "public" for base class? Any reason?

  • @alfonsogonzalez-astrodynam2207
    @alfonsogonzalez-astrodynam2207 4 ปีที่แล้ว

    Great explanation! thank you

  • @kindpotato
    @kindpotato 4 ปีที่แล้ว

    This guy types so FAST

  • @alexandruandricsak4051
    @alexandruandricsak4051 6 ปีที่แล้ว +2

    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!

  • @koobyroory
    @koobyroory 6 ปีที่แล้ว

    What IDE do you use? it looks like something I'd want to try out.

    • @nickpappas6109
      @nickpappas6109 6 ปีที่แล้ว

      King Luke it’s visual studio

    • @v0idptr
      @v0idptr 6 ปีที่แล้ว

      Visual Studio

    • @koobyroory
      @koobyroory 6 ปีที่แล้ว

      Oh haha, thanks guys!

  • @yonlehman
    @yonlehman 4 ปีที่แล้ว

    Why can't the compiler warn you when you are inheriting from a class without a virtual destructor?

  • @bloodwolf8307
    @bloodwolf8307 4 ปีที่แล้ว

    cool

  • @someguy2910
    @someguy2910 5 ปีที่แล้ว

    "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

  • @AbhishekKr1902
    @AbhishekKr1902 5 ปีที่แล้ว

    I am new to C++ and OOPS, can somebody please explain what is the use case of when you do:
    Base* poly = new Derived();

  • @swagluke2370
    @swagluke2370 6 ปีที่แล้ว

    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++.

    • @vixellar7933
      @vixellar7933 6 ปีที่แล้ว +1

      The core engine is made in c++ and the tools used in engine is made with c#

    • @swagluke2370
      @swagluke2370 6 ปีที่แล้ว

      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#.

    • @swagluke2370
      @swagluke2370 6 ปีที่แล้ว

      Thank you for your response. that makes a lot of sense now.

    • @swagluke2370
      @swagluke2370 6 ปีที่แล้ว

      Thanks for telling me what should be in an engine! i kind of needed that

  • @mixedbytc
    @mixedbytc ปีที่แล้ว

    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.*

  • @earthserenityforever
    @earthserenityforever 6 ปีที่แล้ว

    what is the software/hardware you use to record these tutorials :)

  • @reverse5461
    @reverse5461 6 ปีที่แล้ว

    You can see that he is aging if you compare him with the first video

  • @boltgreywing1718
    @boltgreywing1718 6 ปีที่แล้ว

    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.

  • @swagluke2370
    @swagluke2370 6 ปีที่แล้ว

    Help, i have a function in a class:
    class Logging {
    public:
    void Log(const char* text) {
    std::cout

    • @swagluke2370
      @swagluke2370 6 ปีที่แล้ว

      What if i wanted to do Log("FPS: " + fps); // Fps doesnt exist but just an example

    • @swagluke2370
      @swagluke2370 6 ปีที่แล้ว

      thanks

  • @JohannesEckhoff
    @JohannesEckhoff 6 ปีที่แล้ว

    I don't really understand why the base constructor is called when a derived object is constructed. Can someone ELI5?

    • @Djzaamir
      @Djzaamir 6 ปีที่แล้ว

      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

    • @JohannesEckhoff
      @JohannesEckhoff 6 ปีที่แล้ว

      Thank you.

  • @custard131
    @custard131 6 ปีที่แล้ว

    why is 'virtual' not the default state like it is in other languages?

    • @TheLordoftheDarkness
      @TheLordoftheDarkness 3 ปีที่แล้ว +1

      Because it adds overhead on both the cpu and memory.

  • @aleksandarstanisic1848
    @aleksandarstanisic1848 6 ปีที่แล้ว

    uff more leaks
    ]

  • @shorakie5068
    @shorakie5068 6 ปีที่แล้ว +1

    when will the Game Engine Tutorial series began ??

  • @tritranminh4990
    @tritranminh4990 6 ปีที่แล้ว

    So, should I make every destructor virtual just to be safe?

    • @TheCherno
      @TheCherno  6 ปีที่แล้ว +1

      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.

  • @mateoivanov4998
    @mateoivanov4998 6 ปีที่แล้ว

    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 ?)

  • @SimplySpiceIt
    @SimplySpiceIt 6 ปีที่แล้ว +1

    Second comment:

    • @vertigo6982
      @vertigo6982 6 ปีที่แล้ว +1

      Representing Second place... The first loser.. I like your style. Keep up the good work.

  • @astrodot1503
    @astrodot1503 5 ปีที่แล้ว

    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😭😭😭

  • @mateoivanov4998
    @mateoivanov4998 6 ปีที่แล้ว

    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 ?)