[a / b / c / d / e / f / g / gif / h / hr / k / m / o / p / r / s / t / u / v / vg / vm / vmg / vr / vrpg / vst / w / wg] [i / ic] [r9k / s4s / vip] [cm / hm / lgbt / y] [3 / aco / adv / an / bant / biz / cgl / ck / co / diy / fa / fit / gd / hc / his / int / jp / lit / mlp / mu / n / news / out / po / pol / pw / qst / sci / soc / sp / tg / toy / trv / tv / vp / vt / wsg / wsr / x / xs] [Settings] [Search] [Mobile] [Home]
Board
Settings Mobile Home
/g/ - Technology


Thread archived.
You cannot reply anymore.


[Advertise on 4chan]


File: Cplusplus.png (8 KB, 120x135)
8 KB PNG
>a virtual function lets pointers use the One right function for their object
>a virtual destructor uses All destructors of the object
Wait, why? Isn't that confusing?
Why not implement two types of virtual if there's a use case for both?
>>
Because in almost all situations, you still want the inherited destructors of the object to be called. If you don't want that, then you're likely doing something wrong and shouldn't even be bothering with inheritance in the first place.
It doesn't work this way for, e.g., constructors because they take arguments, so automatically calling it at the end would be awkward.
Having two types of virtual might be useful (when overriding a method that takes no arguments), but you're adding more bloat to an already bloated language.
>>
mom told me always eat your vtables
>>
>>108771495
>so automatically calling it at the end would be awkward.
So call it at the start?
>more functionality = more bloat
But it already is bloated. Wouldn't that be you arguing it should be removed instead?
>>
>>108771546
>So call it at the start?
Inherited destructors automatically run at the end. You'd need three virtual method styles to cover all use cases: start, end, and manual. You've gone from two types to three types.
>But it already is bloated.
Right, so why add more functionality which is bloat? The current implementation satisfies all sane use cases. It's way too late now anyway to change this.
>>
Because that's how Bjorn Seppels programmed it. Do you think you're smarter than him?
>>
`virtual` in inheritance hierarchies also behaves differently so you can do fun stuff like this.
#include <iostream>

class Other
{
public:
virtual ~Other() = default;
virtual void g() = 0;
};

class Other1 : virtual public Other
{
public:
virtual ~Other1() = default;
virtual void g() override
{
std::cout << "other1" << "\n";
}
};

class Other2 : virtual public Other
{
public:
virtual ~Other2() = default;
virtual void g() override
{
std::cout << "other2" << "\n";
}
};

class Base : virtual public Other
{
public:
virtual ~Base() = default;
virtual void f() = 0;
};

class Derived1 : public Base, virtual public Other1
{
public:
virtual ~Derived1() override = default;
virtual void f() override
{
std::cout << "Derived1" << "\n";
}
};

class Derived2 : public Base, virtual public Other2
{
public:
virtual ~Derived2() override = default;
virtual void f() override
{
std::cout << "Derived2" << "\n";
}
};

int main()
{
Base *d1 = new Derived1;
Base *d2 = new Derived2;
d1->f();
d1->g();
d2->f();
d2->g();
delete d1;
delete d2;
}
>>
>>108771683
Usecase when no new projects are being written in C++, but Rust?
>>
>a virtual function lets pointers use the One right function for their object
>a virtual destructor lets pointers use the One right destructor for their object (which in turn calls all the necessary destructors)
fify
>>
>>108771696
usecase for living in rustroon fantasy land?
>>
>>108771720
>calls all the necessary destructors
It calls the current and all prior. That's not only the necessary, that's all.
>>
>>108772149
all destructors are necessary
>>
File: 1715495727892.png (93 KB, 857x275)
93 KB PNG
>>108771458
>adding a private function to a class requires all source files using the class to be recompiled
>>
>>108772353
Which language are you using that compiles only half of your program when you hit compile?
>>
>>108772420
I bet this post really seemed smart in your head.
>>
>>108772499
>anime vomit reaction image
>filename is the same as the day he saved it from 4chan
>when questioned, quips back with a stock phrase
I guess I won.
>>
>>108772543
Not an argument.
>>
>>108772420
C++ with incremental LTCG
>>
>>108772353
Its indeed one of the worse design flaws of c++. I made my own fork of clang to get rid of that horrible limitation. In my fork, you can define out-of-line methods without needing a corresponding forward declaration in the class body.
>>
FUCK C++
>>
>>108772353
private is just a suggestion

#define private public
#include "Foo.h"
#undef private

also access control is not checked during explicit template instantiation
you can also hack the vtable
and you can also friend a subclass to give it access to privat emembers
>>
>>108773450
Just use C then.
>>
>>108773786
???
>>
>>108773206
Do you have this clang fork published somewhere? Seems interesting.

I can excuse having to recompile client code when adding new private MEMBERS, not functions: in order to allow instances of a class to be stack-allocated, clients must know their size at compile-time, now way around that.

The PIMPL idiom (also widely used in C, see FILE *) allows you to prevent recompilation if private class members change: now the full declaration of the class is hidden from client code, which only manipulates the corresponding objects through pointers. The drawback, of course, is that you must now manage allocation of the objects in some way other than the stack.

However, there is absolutely no technical reason to force users of a class to be recompiled when adding a new private FUNCTION, since private functions don't change the information that client code needs to use the objects: they are not - by definition - part of the public interface, and they do not affect size or layout of the objects.

In Go and Common Lisp, for instance, methods do not "belong" to classes: they are defined "outside" classes, just like free functions. This is more than a mere syntactic convenience: adding methods to existing classes becomes trivial this way.
>>
>>108771740
No new projects are being written in C++ and big corpo is shilling Rust. Now, your reason for sticking with obsolete?
>>
>>108774006
One does not simply learn Rust, Rust is a transition, a full ego death and rebirth. Everything you were before ceases to be.
>>
File: 1758950510894425.jpg (24 KB, 480x479)
24 KB JPG
the mechanics of calling destructor of every class in inheritance chain does not use virtual calls. the virtual pointer is only there to point to the leaf-most destructor. rest is called in the same way as member destructors
>>
>>108772420
AI, snailcat.
>>
>>108774000
PIMPL can be done on the stack just fine. In a naive implementation the owning class can allocate a buffer as a member variable then construct the impl over that (using e.g. placement new). With this approach you do need to use composition rather than inheritance and add a friend declaration but it's perfectly viable.
>>
>>108772353
why does this matter

t. not knower
>>
This is why I use Rust. Imagine caring about useless OOJeet bullshit like this. C++ is just exhausting.
>>
>>108774290
Cpp has long-ish compile times and #including a file means just copypasting it. Suppose 15 source files depend on some child class, now if you modify the private contents of the parent class the compiler marks the child class as dirty, so then any file that included the child class (which remember is just a fancy way of saying copypasting) is marked as dirty too, and then every other file including the now dirty file is also dirty, etc. so you added one private function and now maybe you need to recompile 50 files (or “translation units” like they call them)
But private in cpp isn’t really enforced at the compiler level so you can’t get around that fact, you need to recompile because of the way the language works.
>>
>>108774175
While this does have some benefits, you still need to create a "handle" class that holds a buffer large enough. If the actual implementation class becomes larger than that, the buffer declared in the handle class will have to grow, thus triggering recompilation.

A fully opaque object cannot possibly be allocated on the stack, but, on the other hand, code using it will never need to be recompiled even if you add a million members, provided that the public interface is unchanged.
>>
>>108771520
Underrated.
>>
>>108771458
>Wait, why?
because how the fuck else are you gonna clean up private variables in base classes you don't even have access to or know about?
>>
>>108774480
You are correct, to a degree. A stack frame needs to know the alignment and size constraints of any objects allocated into it, so for more general use you will communicate the buffer size and alignment in the class declaration for the interface. However, if you are willing to accept a more restrictive use you use continuation-passing style and generate stack frames with the requisite buffer(s) as needed. If you need runtime allocation and do not want to accept the overhead of context pushes (e.g. push {lr} for non-leafs) you can call out to a C function that allocates a VLA and passes that back into your C++.
>>
>>108774362
and this is despite the private function not being used/reachable by child classes, right? So essentially recompiling for nothing?
>>
>>108775946
That depends on the changes made in the private portion of the class. It is possible to make changes that are not observable at compile time to other TUs and it is possible for a compiler vendor to provide dependency information that would allow to detect that a rebuild is not strictly needed. No compiler vendor does this. I have not looked into this very closely but I would not be surprised if C++ modules help with this problem.
>>
>>108776427
thanks sweetie



[Advertise on 4chan]

Delete Post: [File Only] Style:
[Disable Mobile View / Use Desktop Site]

[Enable Mobile View / Use Mobile Site]

All trademarks and copyrights on this page are owned by their respective parties. Images uploaded are the responsibility of the Poster. Comments are owned by the Poster.