C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Call virtual method from base's destructor

From: Nikolay Mihaylov <nmmm_at_[hidden]>
Date: Wed, 29 May 2024 22:36:16 +0300
my 5 cents

when base class d-tor is called all other children d-tors are already
called and may be children object / classes may not be in "correct" state -
e.g. memory freed, but pointer pointing somewhere etc.

I did not follow the example, but if we have COMPort as a base and
RS232_Boost as a child class, closing the port should be done in
RS232_Boost d-tor.

And yes, I agree it would be nice if you can close the port in COMPort
d-tor, but in reality the RS232_Boost might not even exist at that moment.

Nikolay

On Wed, May 29, 2024 at 10:28 PM Lorand Szollosi via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> Hi,
>
> You have an XY-problem.
>
> On Wed, May 29, 2024 at 12:38 PM Frederick Virchanza Gotham via
> Std-Proposals <std-proposals_at_[hidden]> wrote:
>
>> class RS232 : public IRS232 {};
>> virtual ~RS232(void) noexcept { this->Close(); }
>> RS232_Microcontroller::~RS232_Microcontroller must call
>> "this->Close()"
>> RS232_Win32::~RS232_Win32 must call "this->Close()"
>> RS232_Boost::~RS232_Boost must call "this->Close()"
>>
> The things you'd like to run *before* destructor is not in the *base*,
> but in the *descendant*.
>
> Thus, you *can* have a base for the interface:
> class IRS232 { /* common stuff, any virtuals if you don't like concepts */
> };
>
> You have an implementation hierarchy:
> class RS232 : public IRS232 { /* dtor doesn't call close */ };
>
> You have the system-specific implementations of any number of layers:
> class RS232_Arch_Impl : public RS232 { /* dtor still doesn't call close */
> };
>
> And you have the top layer:
> template<typename T>
> struct RS232_Top : T {
> ~RS232_Top { Close(); } // you're free to have preClose(), Close(),
> afterClose(), etc.
> };
>
> using RS232_Arch = RS232_Top<RS232_Arch_Impl>;
>
> This ensures that Close() is called *before* dtor of your implementation.
> And it's done.
>
> As for the proposed feature,
>
>
>> virtual ~IRS232(void) noexcept derived_invokes(Close) {}
>>
> [...]
>
>> The purpose of this proposed new feature is that instead of creating
>> bugs that are discovered a runtime, you get a compiler error.
>
> It's equivalent to the halting problem (i.e., Turing-complete) to check
> for an arbitrary code whether it calls a function. (It could call it
> conditionally e.g. in a loop or it could be called from a function / lambda
> it conditionally calls, or via a function ptr, or via a pointer that was
> written to a file and then read back, etc.) So it cannot be verified in
> compile-time.
>
> Also, since it's 2024..., I'd consider twice before writing virtual for an
> interface. We have CRTP, concepts, even deducing this. I'd argue that, on
> most architectures virtual is nowadays mainly for forward compatibility,
> i.e., to be able to support descendants whose implementation is not yet
> available at the time you compile the calling code (a notable exception to
> this is cacheless MIPS architectures). That simplifies the code even more I
> think.
>
> Thanks,
> -lorro
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2024-05-29 19:36:54