Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ override a member variable

This may be a silly question, but I was wondering if it is possible to override the type of a member variable as long as it is a child type.

Basically I have a parent class A that has a variable like so:

TSubclassOf<AItem> ItemClass;

then in class B which extends class A I was wondering if I could change the type to a different one like so:

TSubclassOf<AWeapon> ItemClass;

where Weapon extends Item, so it is still a subclass of Item.

Is this possible?

If not, is it possible to hide a variable in a child class? i.e. I could hide ItemClass and create a new variable called WeaponClass.

Thanks in advance for the help

like image 986
Pectus Excavatum Avatar asked Jun 22 '16 18:06

Pectus Excavatum


2 Answers

By declaring TSubclassof<AWeapon> ItemClass; in the derived class, you are basically hiding ItemClass in the base class. So, it will look like you "changed" the type, but you didn't, only in the derived class will you see the new type variable.

If you call a member function of the base class, which accesses ItemClass, it will use the "old" type variable.

If not, is it possible to hide a variable in a child class? i.e. I could hide ItemClass and create a new variable called WeaponClass.

That's possible, you could declare ItemClass as a private variable, so that the derived class doesn't have access to it. Then when you can create WeaponClass, without there being a ItemClass in the derived class.

like image 77
Rakete1111 Avatar answered Oct 05 '22 03:10

Rakete1111


It depends, as many things do, on visibility. If ItemClass is private, then class B wouldn't even see it in the first place, so there's no chance whatsoever of a naming clash. If it's protected, then... things get a little complicated. It won't throw any errors, but you'll hide the name in the subclass, but not in the superclass. See this bit of code as an example:

#include <iostream>
#include <string>

struct message {
    std::string the_message;
    message() : the_message("default string") {}
    message(std::string a) : the_message(a) {}
    virtual ~message() = default;

    virtual void foo() { std::cout << the_message << std::endl; }
};

struct message_sub : message {
    int the_message;

    message_sub(int a) : the_message(a) {}
};

int main(int, char**) {
    message *a_message = new message_sub(12);
    a_message->foo();
    delete a_message;
}

Try it online

As you can see if you run it, the output is not 12, as you might expect, but default string. That's because the superclass method foo will see things in its scope; i.e. it'll see the version whose name you're hiding in the subclass. The only way to fix this problem is to copy-and-paste foo into the subclass, and if it's not virtual in the subclass, there's no way to make it work.

Because of this, I'd advise against whatever you're trying to do here; you can't write a default implementation that uses member variables of the subclasses, only those that exist in the superclass. Two variables with the same name but different types are different variables. If this is just wondering if you can safely name things whatever you want, yes, you can, especially if they're private.

like image 28
Nic Avatar answered Oct 05 '22 05:10

Nic