3 ms·
I had to write C++ yesterday and hated every second of it, from the clunky header files, to the errors that make no sense, to the can't make a cyclic dependency
by Ygg2 10y ago
I had to write C++ yesterday and hated every second of it, from the clunky header files, to the errors that make no sense, to the can't make a cyclic dependency between classes i.e.
class A { B: b}
class B { a: A}
Long story short - I was to create a wrapper around a Poco::Runnable, so you can use the wrapper as a Poco::Runnable (don't ask why, it's TEH LAW) but without extending it.
- gte525u 10y agoYou should be able to do that with either references or pointers between classes with a forward declaration. In essence: class B; class A { B* b;} class B { A* a;}
- ygra 10y agoYou can only do that when using pointers or references: class B; class A { B* b; } class B { A* a; } because the compiler can (obviously) not tell how large the instances of the other class are when you have a field of that type. Remember that the class layout has to be fixed at compile time and both instance sizes depend on one another. That's not solvable. C# does the same, actually: struct A { B b; } struct B { A a; } will cause the following error: test.cs(2,5): error CS0523: Struct member 'A.b' of type 'B' causes a cycle in the struct layout test.cs(6,5): error CS0523: Struct member 'B.a' of type 'A' causes a cycle in the struct layout with classes and references it works, of course: class A { B b; } class B { A a; }
- Ygg2 10y agoThis is also what I attempted, and as I remember it didn't work either, though to be honest I was really worn out fighting the obscure compiler errors by that point, I might have missed a sigil somewhere. I spent good solid 30min trying to understand why defining and not defining my constructor was causing issues, to realize that the constructor error was actually a previous error, somewhere above the constructor. Rust, also notes where and how you created an infinite loop.
- netheril96 10y agoYour compile error is likely because you use references instead of pointers. Reference as a class member is really hard to get right because it can be initialized only once, and cannot be copied or moved.
- humanrebar 10y agoNot sure what you're trying to do, but: class A; class B; // 'forward declaration' if you want to google class A { unique_ptr<B> b; }; class B { unique_ptr<A> a; }; ...generally classes instantiating each other is a sign that your design needs rearranged, but it has its uses when writing graph types.
- okasaki 10y agoBecause it doesn't make sense. These types would have infinite size.
- xg15 10y agoC++noob here, but: Given that the members in your example are no pointers but actual substructures within your data structure, wouldn't that result in an infinite data structure? Therefore it sewms quite logical to me it's not allowed. Disallowing cyclical dependencies via pointer would make no sense though.
- humanrebar 10y agoRight. C++ objects are values, not references to values like in almost all other languages. So C++ needs to know the sizes of everything to construct them. If you tried to write out the mathematical series describing the ultimate size you would need to allocate for A or B, you would end up with a value approaching infinity.
- TheCoelacanth 10y agoThis is probably my favorite thing about C++. Values are so much easier to reason about than references.
- Ygg2 10y agoIt's more of a simplification. Although, I did try references and they didn't compile either. In fact, if I remember correctly the error was "forward declaration forbidden". After spending about 10-12 years away from C++, I was pretty much on novice level. I remember some things, but most details and day to day specifics are gone. It did serve as a fresh reminder why I hate C++. Or more precisely, why I hate C++ compilers.