C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Public inheritance with banned conversion to base

From: Filip <fph2137_at_[hidden]>
Date: Thu, 23 Jan 2025 09:16:41 +0100
Maybe a stupid question but why wouldn’t the STL containers be marked with final if it is not encouraged to inherit from them?

Cheers, Filip

Wiadomość napisana przez Jeremy Rifkin via Std-Proposals <std-proposals_at_[hidden]> w dniu 23 sty 2025, o godz. 02:21:


Hi,
As others mentioned, private and protected inheritance work (though they don't make this a fully safe thing to do). Inheriting from a standard library container is an anti-pattern and I'd much rather see extended functionality, at least as far as member functions go, enabled through extension methods or the proposed pipeline rewrite operator.

Cheers,
Jeremy

On Wed, Jan 22, 2025 at 9:29 AM Dennis Gusev via Std-Proposals <std-proposals_at_[hidden]> wrote:

If you look up "inheriting from STL containers", the top results from SO and reddit all mention it being a bad practice since standard containers aren't designed to be inherited from.


Specifically, they dont have virtual destructors so there's a risk of UB from deleting through pointer to base.


Also if you override any existing member functions and accidentally pass your derived class to a function expecting a regular STL container, the original base class member functions will get called instead(not to mention potential object slicing).


What if C++ had a way to publicly inherit from a class and also ban base class conversions to avoid potential usage pitfalls with something like this:


class Base

{

    public: 

    void foo()

    {

        std::println("Base foo");

    }


    void bar()

    {

        std::println("Base bar");

    }

};


class PublicDerived : public Base

{

    public: 

    void foo()

    {

        std::println("PublicDerived foo");

    }

};


class ComposedDerived : composed Base // new type of inheritance

{

    public: 

    void foo()

    {

        std::println("ComposedDerived foo");

    }

};


void testFoo(Base& val)

{

    val.foo();

}


int main()

{

    PublicDerived publicDerived;

    publicDerived.foo(); // prints "PublicDerived foo"

    publicDerived.bar(); // accessible, prints "Base bar"

    testFoo(publicDerived); // uh oh, prints "Base foo" even though we have our own foo


    ComposedDerived composedDerived;

    composedDerived.foo(); // prints "ComposedDerived foo"

    composedDerived.bar(); // still accessible, prints "Base bar"

    testFoo(composedDerived) // doesn't compile, conversion to base forbidden


    return 0;

}


Has anything like this ever been proposed?


Seems like it would address a common use case by making it possible to extend behavior of classes safely even if they weren't designed to be inherited from(i.e. no public virtual or protected nonvirtual destructor)

--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2025-01-23 08:16:54