Brace Initialize struct with virtual functions
Asked Answered
A

2

7

Brace initialization

        struct A
        {
            int a;
            int b;
            void foo(){}
        };

        A a{1, 2};

It works fine. But if change foo to a virtual function, It will not compile with error,

Error C2440 'initializing': cannot convert from 'initializer list' to

I find this,

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

But what's the reason behind it?

Apron answered 24/6, 2021 at 8:26 Comment(1)
I may be totally wrong, but I know some of the things mentioned in the link you posted, like virtual methods, private or protected non-statics, base classes, ... could (or really 100% do) change the layout of the objects in memory (addition of a vptr, privates and protected could potentially be rearranged by the compiler - any of these would also break std::is_standard_layout<T>. So maybe this wouldn't allow aggregates to work as expected. The user provided constructor is another story - to me it's about how to choose between it and an aggregate init. You can add a ctor with initializer_listMicroscopy
L
0

There isn't a way. like in this text you mentioned

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

this means that a class/struct or an array that has

  • no user-provided constructors
  • no private or protected non-static data members
  • no base classes
  • and no virtual functions

is an aggregate. and only an aggregate can have brace initialization. so in this case, your struct has a virtual function that violates one of the laws above and makes it a non-aggregate.

I don't know why this is the case.

I guess that if your struct is similar to the struct in c then your struct would work.

so like Hassan's answer, you should use a parameterized constructor instead.

Loftis answered 18/4, 2022 at 3:56 Comment(1)
This answer is basically a copy-and-paste of the original question, which disqualifies this as an answer, because this does not answer anything. Please don't do this again.Breakaway
S
1

Why don't you use a parameterized constructor with virtual void foo() {}

struct A
{
    int a;
    int b;
    A(int a, int b)
    {
        this->a = a;
        this->b = b;
    }
    virtual void foo() {}
};
A a{ 1, 2 }; 
Stigmatism answered 24/6, 2021 at 8:37 Comment(1)
The idea with that constructor is not bad but I would prefer: A(int a, int b): a(a), b(b) { } i.e. prefer initializers over assignment (though it probably doesn't make that difference for ints).Fives
L
0

There isn't a way. like in this text you mentioned

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

this means that a class/struct or an array that has

  • no user-provided constructors
  • no private or protected non-static data members
  • no base classes
  • and no virtual functions

is an aggregate. and only an aggregate can have brace initialization. so in this case, your struct has a virtual function that violates one of the laws above and makes it a non-aggregate.

I don't know why this is the case.

I guess that if your struct is similar to the struct in c then your struct would work.

so like Hassan's answer, you should use a parameterized constructor instead.

Loftis answered 18/4, 2022 at 3:56 Comment(1)
This answer is basically a copy-and-paste of the original question, which disqualifies this as an answer, because this does not answer anything. Please don't do this again.Breakaway

© 2022 - 2024 — McMap. All rights reserved.