Home > front end >  Overriding protected field members in C not working?
Overriding protected field members in C not working?

Time:10-26

In the following, I expected class Child's protected field member _AorB to be of type B, and not A, but reality shows otherwise.

What am I mis-understanding, and how can I adjust the code for the desired behavior?

class A{
    public:
       void doit(){
           std::cout<<" this is A!"<<std::endl;
       }
    
};

class B{
    public:
       void doit(){
           std::cout<<" this is B!"<<std::endl;
       }
    
};

class Parent{
    public:
      void doit(){
          _AorB.doit();
      }
      protected:
        A _AorB;
};

class Child: public virtual Parent{
    protected:
      B _AorB;
};

int main()
{
    cout<<"Hello World";
    auto c = Child();
    c.doit(); // I expected this to print "This is B" because c is Child(), and Child class's _AorB is of type B.
    return 0;
}

CodePudding user response:

You can make such changes:

template <typename AorB>
class Parent{
    public:
      void doit(){
          _AorB.doit();
      }
      protected:
        AorB _AorB;
};

class Child: public virtual Parent<B> {
}

Also take a look at What are the rules about using an underscore in a C identifier?

  • Reserved in any scope, including for use as implementation macros:
    • identifiers beginning with an underscore followed immediately by an uppercase letter

CodePudding user response:

273K's answer is excellent.

Depending on what kind of problem you are trying to solve and how the data is held in the hierarchy, you could use a std::variant<A, B> to allow "flippy" behavior based on the type, and access that member variable through a virtual getter member function.

#include <iostream>
#include <variant>

class A {
public:
    void doit() {
        std::cout << " this is A!\n";
    }
};

class B {
public:
    void doit() {
        std::cout << " this is B!\n";
    }
};

class Parent {
public:
    virtual ~Parent() = default;
    void doit() {
        auto ab = get_AorB();
        std::visit([](auto arg) { arg.doit(); }, ab);
    }
    virtual auto get_AorB() -> std::variant<A, B> {
        return _a;
    }
protected:
    A _a;
};

class Child : public virtual Parent {
protected:
    B _b;
    auto get_AorB() -> std::variant<A, B> override {
        return _b;
    }
};

int main() {
    std::cout << "Hello World";
    auto c = Child();
    c.doit(); // "this is B!"
}
  •  Tags:  
  • c
  • Related