Reputation: 1463
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
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
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