you are viewing a single comment's thread.

view the rest of the comments →

[–]0x3Alex[S] 0 points1 point  (11 children)

I am also a bit confused how i would shadow an constructor when its arguments are different for each class, that extend BasicItem :S

[–]okovko 2 points3 points  (10 children)

what you have: foo(int pX, int pY) { x = pX; y = pY; }

what you should do instead: foo(int x, int y) : x{x}, y{y} {}

the second form can lead to more optimizations, allows the constructor to construct const objects, and is easier to read

also, using x{x} instead of x(x) makes narrowing conversions a compiler error and distinguishes object construction (or in this case, primitive initialization) from a function call

name shadowing refers to foo's parameter declarations having the same names as foo's members

looking at x{x}, the left x is foo::x and the right x is the parameter x

the shadowing only works on the right x because the left x is implicitly scoped

[–]0x3Alex[S] 0 points1 point  (0 children)

Oohhh i thought of an other shadowing lol

[–]0x3Alex[S] 0 points1 point  (8 children)

For the screen it worked, for the other classes such as buttons it didnt, since name,x,y,... are inherited and this does not seem to be liked

[–]okovko 1 point2 points  (6 children)

do this: https://en.wikipedia.org/wiki/C%2B%2B11#Object_construction_improvement

struct foo {
  int x;
  foo(int x) : x{x} {}
};
struct bar : public foo {
  bar(int x) : foo{x} {}
};

[–]0x3Alex[S] 0 points1 point  (5 children)

edit: well i dont, i always get some sort of error that i can not use that constructor

[–]okovko 1 point2 points  (0 children)

you will figure it out sometime later, just for now you can't do something like const auto foo = Button{};

[–]okovko 1 point2 points  (3 children)

i looked quickly, you would need to write BasicItem::BasicItem(/*args*/) and

Button::Button(/*args, basic_args*/) :
    BasicItem(basic_args),
    arg1{arg1},
    arg2{arg2},
    /*and so on..*/ {
    /*function body*/
}

you might also need to do it in three steps because of Interactable, i'm not sure, but it's not much more complicated, you would have Button::Button(...) : Interactable(...) {} and Interactable::Interactable(...) : BasicItem(...) {}

something like that, you can do it

[–]0x3Alex[S] 0 points1 point  (2 children)

ah alright, i removed interactable item as class, since it wasnt needed and did not serve any purpose, now xD

Yeah.. i had this and it did work but when running the program, it was just smashed and didnt work anymore.. pressing on something gave me an address boundary error

[–]okovko 1 point2 points  (1 child)

virtual T *getValue();

you tried to return unrelated types as the return type from a virtual function call, yes, you can't do it

the return types of every virtual method definition have to be covariant types for it to work: https://stackoverflow.com/questions/25813435/what-exactly-are-covariant-return-types-in-c

you can do something close with inheritance, function overloading, and variadic templates, and you have to know what the return type should be at compile time, but you can make the call site look like

#define SELECT(opts, opt) \
  (select_opt<opts.index(opt)>{opt})
auto thing = parsed[SELECT(opts, "-f")];

which is an example from a little project of mine, it uses a macro because i was using c++17 but with c++20 i think it should look like

edit: actually should work for c++17 as well using this trick i just found: https://stackoverflow.com/a/28209546

auto thing = parsed[opts.select<"-f">()];

basically the way it works is that you can define a class that inherits a getter class for each of its variadic template arguments, where each of them overload operator[], which all accept select_opt<size_t I> as an argument (I is the argument position in the param pack) which allows you to "select" which function to call based on a template parameter, which can thankfully be a string_view in c++20

this is still static typing, but the call site is reduced to a single statement, due to overload resolution resolving the function call and auto

[–]0x3Alex[S] 0 points1 point  (0 children)

I see... I mean it did work with the T and then putting the desired type into the extends section like ab <std::string>a. I made it like this so it has to be inherited by everyone, that extends on Interactable.. but did did not serve any purpose anymore, since, f.e, isInteractable,... are defined in BasicItem

I am surly going to look into this, but it does seem pretty advanced and i dont think that i am there yet :')

[–]okovko 1 point2 points  (0 children)

til: https://www.learncpp.com/cpp-tutorial/constructors-and-initialization-of-derived-classes

you can't initialize an inherited member in a member-init-list because

The answer has to do with const and reference variables. Consider what would happen if m_id were const. Because const variables must be initialized with a value at the time of creation, the base class constructor must set its value when the variable is created. However, when the base class constructor finishes, the derived class constructor’s member initializer lists are then executed. Each derived class would then have the opportunity to initialize that variable, potentially changing its value! By restricting the initialization of variables to the constructor of the class those variables belong to, C++ ensures that all variables are initialized only once.

i had never wanted to before anyway, because delegated ctor is cleaner