Luke Collins
Luke Collins

Reputation: 1463

C++ Inheritance: Do I have to repeat parent attributes in derived classes?

If I separate my classes into header/implementation files, is it possible to have inheritance without needing to redeclare inherited attributes in the child class?

Let me clarify with an example. Why is this allowed (taken from here):

#include <iostream>

using namespace std;

// Base class
class Shape {
   public:
      void setWidth(int w) {
         width = w;
      }
      void setHeight(int h) {
         height = h;
      }

   protected:
      int width;
      int height;
};

// Derived class
class Rectangle: public Shape {
   public:
      int getArea() { 
         return (width * height); 
      }
};

int main(void) {
   Rectangle Rect;

   Rect.setWidth(5);
   Rect.setHeight(7);

   // Print the area of the object.
   cout << "Total area: " << Rect.getArea() << endl;

   return 0;
}

But this isn't (try compiling here):

#include <string>
#include <iostream>

// HEADER FILE
class Person {   
public:
    virtual void speak() = 0;

protected:
    std::string name;
    std::string surname;
};

class Programmer : public Person {
public:
    Programmer(std::string, std::string);
};

// CPP FILE
Programmer::Programmer(std::string name, std::string surname) : 
    name(name), 
    surname(surname) 
{}

void Programmer::speak(){
    std::cout << "My name is " + name + " " + surname + " and I like to code!";
}

Upvotes: 0

Views: 2650

Answers (2)

SergeyA
SergeyA

Reputation: 62603

I am not sure what is confusing. Member initializer list only allows to specify base class(es) or direct members of this class. Because of that, your second example is not compiling.

At the same time, derived classes have access to public and protected member of their base(s), so this is why first example is OK.

An interesting observation is that following code will compile:

Programmer::Programmer(std::string name_, std::string surname_) {
    name = name_;
    surname = surname_;
}

Note, this will mean name and surname will be first default-initialized (to empty strings) and than they will be assigned to the values passed in the Programmer constructor. This is efficiency loss, which might be very noticeable under certain circumstances.

The proper way of solving this idiomatically is buy giving Person a constructor which accepts two string arguments and initializes the members, and than calling this constructor from Programmer constructor.

Upvotes: 4

Robert Andrzejuk
Robert Andrzejuk

Reputation: 5232

In the Programmer constructor, in the initializer list the variables initialized can only be variables directly from that class or a base class constructor.

But in the body of the member functions/constructors inherited variables can be used, if they are effectively public or protected.

Upvotes: 0

Related Questions