• 3 Posts
  • 9 Comments
Joined 1 year ago
cake
Cake day: June 30th, 2025

help-circle




  • It was a simplified example.

    B and C can’t share any other attributes without duplication of code

    struct A {
        [[nodiscard]] virtual std::uint32_t DoSomething() = 0;
    };
    
    struct B : A {
        std::uint32_t DoSomething() override { 
            return 0;
        }
    };
    
    int main() {
        B b;
        b.DoSomething(); //no warning
    }
    

    even if you use virtual attributes aren’t inherited.

    If you ment members instead of attributes this is unrelated to virtual:

    struct A {
        std::uint32_t a;
    };
    
    
    struct B : A {
        void DoSomething() { 
            std::println("B"); 
        }
    };
    
    struct C : A {
        void DoSomething() { 
            std::println("C"); 
        }
    };
    

    Now the member is shared and it works fine and there is no virtual.

    There’s also no strict enforcement of inheritance.

    True, but neither is there when just using virtual:

    struct A {
        virtual void DoSomething() = 0;
    };
    
    struct B : A {
    
    };
    

    This compiles fine if final is not added.

    Not that its an issue as reflection has solved this problem:

    consteval std::string_view HasMethods(std::meta::info impl, std::meta::info iface) {
        constexpr auto ctx = std::meta::access_context::unchecked();
        for (auto fn : members_of(iface, ctx)) {
            if (!is_function(fn) || is_special_member_function(fn)) continue;
            bool found = false;
            for (auto cand : members_of(impl, ctx))
                if (is_function(cand) && has_identifier(cand) && identifier_of(cand) == identifier_of(fn) && type_of(cand) == type_of(fn))
                    found = true;
            if (!found)
                return std::define_static_string(std::string(identifier_of(impl)) + " is missing " + display_string_of(fn));
        }
        return {};
    }
    
    
    struct A {
        void DoSomething();
    };
    
    struct B  {
    
    };
    static_assert(HasMethods(^^B, ^^A).empty(), HasMethods(^^B, ^^A));
    
    // g++ -std=c++26 -freflection main.cpp
    // main.cpp:30:41: error: static assertion failed: B is missing void A::DoSomething()
    // 30 | static_assert(HasMethods(^^B, ^^A).empty(), HasMethods(^^B, ^^A));
    

    Now you get the strict enforcement of inheritance and no virtual.


  • Why does it make zero sense in C++?

    edit: simplified example of what i mean

    struct A {
        virtual void DoSomething() = 0;
    };
    
    struct B : A {
        void DoSomething() override { 
            std::println("B"); 
        }
    };
    
    struct C : A {
        void DoSomething() override { 
            std::println("C"); 
        }
    };
    
    void InvokeDoSomething(A* a) {
        a->DoSomething();
    }
    

    vs

    struct B {
        void DoSomething() { 
            std::println("B"); 
        }
    };
    
    struct C {
        void DoSomething() { 
            std::println("C"); 
        }
    };
    
    template <typename T>
    void InvokeDoSomething(T* t) {
        t->DoSomething();
    }