0

Modified the question a bit, thanks for your help on this!

Is there a way to change Parent's constructor(e.g. change the value of protected field) when initialize the Child class.

For example, I have two class - Base and Child below. In the Base constructor, string 'a' will be assigned to a protected field - 'a_' and 'val'(e.g. if a is "str", then a_ is 'a', val is 'a!').

There is a Child class that inherits class Base, and the constructor takes two arguments - string a and b.

What I want is assign 'a+b+"!"' to val, e.g. a = "first ", b = "second", then a_ is "first", b_ is "second", c's value should be "first second!"

class Base {
   public:
     explicit Base(string a) : a_(a), val(a + "!"){};

   protected:
      string a_;
      string val;
}

class Child : public Base {
   public:
     explicit Child(String a, String b) : Base(a), b_(b)...
   
   protected:
      string b_;

}
  • 2
    can you not `explicit Child(String a, String b) : Base(a + b)` ? ([works for me](https://godbolt.org/z/hebbEnbvz)) – Borgleader Jun 29 '22 at 04:07
  • @Borgleader, thanks! Your solution can work in the original version(only 1 field). But I modified the question a bit, and I don't want to change the value of "a_ ". – PepperGooooo Jun 29 '22 at 04:33

4 Answers4

1

You can have 2 constructors:

public:
explicit Base(string a) : Base(a, a + "!") : { };
protected:
explicit Base(string a, string val) : a_(a), val_(val) { };

That way derived classes can set val differently.

Note: you are passing the string by value. It would be better to pass by reference and with move semantic. Or if you can use more modern C++ with a forwarding reference because then you don't have to write so many different versions of the constructor to cover all cases.

Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42
0

You can do it like this. By providing a public getter you can also hide implementation details from your derived classes and from your clients making both classes more maintainable. (I hardly ever use protected members)

#include <string>
#include <iostream>

// using namesapce std;  NO not recommended
// https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice

class Base
{
public:
    explicit Base(std::string a) : val(a) {};

    const std::string& get() const noexcept
    {
        return val;
    }

private:
    std::string val;
};

class Child : public Base
{
public:
    explicit Child(std::string a, std::string b) :
        Base(a + b)
    {
    }
};

int main()
{
    Child c("Hello", "World");
    std::cout << c.get();
    return 0;
}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19
0

Try to use the Reference variable for either child or parent while accessing the protected member.

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 29 '22 at 12:20
0

Thanks for all the reply. After reconsideration, I decided to extract a base class(class 'RealBase') from Base class and Child class. I feel the Child class should always obey the rules defined in parent class(e.g. same attributes, same method, etc.), otherwise, it's better to extract an abstract base class that contains the shared attributes.

Here is the codes sample:


class RealBase {
   public:
      RealBase(string a) : a_(a) {};

   protected: 
      string a_;

}

class Base : public RealBase {
   public:
     explicit Base(string a) : RealBase(a), val(a + "!"){};
   protected:
      string val;
}

class Child : public RealBase {
   public:
     explicit Child(String a, String b) : RealBase(a), b_(b), val_(a+b+"!) {};
   
   protected:
      string b_;
      string val;

}