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

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!";
}

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.

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.

Related

How to create objects that has a variable based on the data from another object that is passed in the constructor

The title may be a little confusing but hear me out. I have this two classes , Entity and Human.
Entity is the parent class of human. When I create a human object, it will require an Entity object passed as argument in the constructor so all the human objects that I create has the same Entity object info.
This is my problem: If I change some data from the Entity object I want to update all the data from the Human objects that I created using that Entity Object in the constructor.
I want to implement this in ones of my University projects so I am allowed to use only the standard library.
I wrote this example so it's easier to understand:
#include <iostream>
using namespace std;
class Entity{
private:
//DATA
int life;
public:
//DEFAULT CONSTRUCTOR
Entity() {life = 100;}
//PARAMETRIZED CONSTRUCTOR
Entity(int life) {this -> life = life;}
//GETTER
int get_life(){return life;}
//SETTER
void set_life(int new_life){life = new_life;}
//FUNCTIONS
void print_life() {cout << "This entity has " << life << " life" << endl;}
};
class Human : public Entity{
public:
//DATA
string name;
//DEFAULT CONSTRUCTOR
Human() {name = "N/A";}
//PARAMETRIZED CONSTRUCTOR
Human(string name, Entity object){
Entity::set_life(object.get_life());
this -> name = name;
}
};
int main(){
//DATA
Entity Human_data(50);
Human Hero("Steve", Human_data);
Human Villain("Mike", Human_data);
//BODY
Human_data.set_life(5000);
Hero.print_life();
//END MAIN
return 0;}
As you can see, after I update Human data life from 50 to 5000, it does not also change Hero and Villain life to 5000 and only changes Human data life to 5000.
I'm assuming that when you call Human_data.set_life(5000) you want to effect all Human objects constructed with the Human_data object.
Here's an example of how you might use references for that. But note putting a reference inside a class is not without consequences. You might use a pointer instead, or even better a smart pointer. But I'm just trying to indicate the general idea.
On a technical note, using references means you have to get used to using initializer lists since references cannot be assigned.
#include <iostream>
using namespace std;
class Entity{
private:
int life;
public:
Entity() : life(100) {}
Entity(int life) : life(life) {}
int get_life() {return life;}
void set_life(int new_life){life = new_life;}
void print_life() {cout << "This entity has " << life << " life" << endl;}
};
class Human { // no inheritence
private:
Entity& entity; // store a reference to the entity
public:
string name;
Human(string name, Entity& object) // object is a reference
: entity(object), name(name)
{
}
void print_life() { entity.print_life(); } // forward to entity
};
int main(){
//DATA
Entity Human_data(50);
Human Hero("Steve", Human_data);
Human Villain("Mike", Human_data);
//BODY
Human_data.set_life(5000);
Hero.print_life();
//END MAIN
return 0;
}
The inheritance could be correct, if all "humans" are also entities (remember that inheritance is an "is a" relationship).
But the implementation is flawed.
Instead of passing an Entity object to the Human constructor, and using the separate and distinct Entity object to control the "life", pass the life itself to the Human constructor, and use set_life on the Human object directly.
Something like this:
class Human : public Entity
{
public:
// By default humans start out with 50 in life
Human(std::string const& name, int life = 50)
: Entity(life), name(name) // Initialize the parent class, then the name
{
}
private:
std::string name;
};
int main()
{
Human hero("The Hero", 5000); // The hero will have 5000 life
Human villain("The Villain"); // The villain will only have 50 life
// Some stuff...
// Update the heroes life
hero.set_life(4000); // Uh oh, the hero have lost 1000 life!
// ...
}

Acessing subclass variable from base class object

Let's say i'm having the following classes in c++
class Animal{}
class Dog : public Animal {
int barkingVolume;
}
However, i don't have the header file for Dog class. But i have the object of Dog of type Animal at runtime.
The question is how I can access the variable barkingVolume?
Animal animalButDogObject;//someone has set the value at runtime
I need to access barkingVolume from animalButDogObject.
Actual scenario from COM/Directshow: I'm having IBaseFilter object which is of type IVendorFilter(custom filter from 3rd party vendor which extended IBaseFilter). While debugging using Visual studio i can see the type is IVendorFilter and it has variables which i need to change. However i cannot figure out how to do it. I cannot find anything like a reflection/evalutation in CPP
I'd rather comment than post an answer, but can't due to lack of reputation, so here we go.
This is pretty bad, but if you know the exact layout of the class you must access, you could just forward declare the whole thing and reinterpret_cast the object you need.
// FooBar.cpp or something
namespace FooBar
{
class Foo {};
class Bar : public Foo
{
public:
Bar(int ival, float fval) : ival(ival), fval(fval) {}
int ival = 0;
float fval = 0.0f;
};
}
// OtherFile.cpp
class ForwardDeclaredBar
{
public:
int ival;
float fval;
};
#include <iostream>
int main()
{
FooBar::Foo* foo = new FooBar::Bar(3, 2.7f);
auto bar = reinterpret_cast<ForwardDeclaredBar*>(foo);
std::cout << "ival = " << bar->ival << ", fval = " << bar->fval << std::endl; // shows expected values
return 0;
}
Again, this is pretty bad since any changes to the "real" class will mess up your result (reinterpret_cast will just shove whatever data it finds into the format you specified).
There are probably many other reasons which I've no idea about. I'm also unsure how well (if at all) this plays with more complex objects.
declare method on Animal (base) class and overwrite it on Dog (derived) class.
// Base class
class Animal
{
public:
virtual int getBarkingVolume() = 0;
};
// Derived class
class Dog : public Animal
{
private:
int barkingVolume = 8;
public:
int getBarkingVolume()
{
return barkingVolume;
}
};
In main method has Animal (base) type and each derived class that implements the appropriate method (getBarkingVolume) will be compatible with that type.
int main()
{
Animal* animal = new Dog();
std::cout<<"barking: "<< animal->getBarkingVolume();
}

Subclass as argument in superclass's member function, C++

I'm new to OOP and I'm working on a C++ project. I isolated my problem to make answering easy but here's the real scenario:
I have a superclass member function, that modifies values inside the object that called it. The modification is based on a value coming from another object of the same class. This object is given to the function as the only parameter. Such as:
void BaseClass::function(BaseClass x) {}
However, I created a subclass. And if the parameter is a subclass type, I want to modify its unique attribute, too.
void BaseClass::function(DerivedClass x) {}
The problem is that the subclass is obviously defined later in the code.
I don't want it as two separate methods, because the calculation algorithm is already written inside, and also the solution I search for doesn't require to change the code at the places where the function is already in use. Besides, every other possibility that comes to mind (e.g. using typeid()) looks silly.
#include <iostream>
#include <string>
class Base
{
protected:
//common attribute
const std::string name;
public:
//constructor for common attribute
Base(const std::string nameString) : name(nameString) {}
//getter
std::string getName() { return name; }
//superclass as parameter
void test1(Base &example) { std::cout << example.getName(); }
//subclass as parameter (I'd want the line below to work)
//void test2(Derived &example) { std::cout << example.getNumber(); }
};
class Derived : private Base
{
protected:
//unique attribute
const std::string number;
public:
//constructor
Derived(const std::string nameString, const std::string numberString) : Base(nameString),
number(numberString) {}
//getter for unique attribute
std::string getNumber() { return number; }
};
int main ()
{
Base object = Base("whatever");
Base baseParameter = Base("base");
Derived derivedParameter = Derived("derived", "12");
object.test1(baseParameter);
//object.test2(derivedParameter);
return 0;
}
What is the standard way of doing it?
You could make test2 a template, and ensure that it's only used with types derived from Base:
template<typename Derived>
void test2(Derived &example)
{
static_assert(std::is_base_of_v<Base, Derived>);
std::cout << example.getNumber();
}
Here's a demo.

cpp access subclass object methods from function that requires superclass object

I have written the following code:
// constructors and derived classes
#include <iostream>
using namespace std;
class Mother
{
public:
int age;
Mother()
{
cout << "Mother: no parameters: \n"
<< this->age << endl;
}
Mother(int a)
{
this->age = a;
}
void sayhello()
{
cout << "hello my name is clair";
}
};
class Daughter : public Mother
{
public:
int age;
Daughter(int a)
{
this->age = a * 2;
};
void sayhello()
{
cout << "hello my name is terry";
}
};
int greet(Mother m)
{
m.sayhello();
}
int main()
{
Daughter kelly(1);
Son bud(2);
greet(kelly);
}
and my question is this:
Since kelly is an instances of a class derived from Mother it makes sense to me that I can pass it into a function that requires an object of type mother ie. greet. My question is this, is it possible to call the sayhello function from within greet such that it will say
it will say "hello my name is terry" instead of "hello my name is clair".
What you're asking for is called "polymorphic behavior" (or "dynamic dispatch") and it is a basic feature of C++. To enable it, you'll need to do a couple of things:
Tag your sayhello() methods with the virtual keyword (i.e. virtual void sayhello() rather than just void sayhello())
Change the greet() method's argument to pass-by-reference or pass-by-pointer, to avoid object-slicing problems (i.e. int greet(const Mother & m) rather than int greet(Mother m))
Once you've done that, the compiler will intelligently choose which sayhello() method to call at run-time, based on the m argument's actual object-type, rather than hard-coding the choice at compile-time based on the type explicitly listed in the greet function's arguments-list.

Personalised name in constructor for different subclasses

Instead of "Car" is there a way to set the name variable of each object according to its class, for example "Turbo 01" or "Tank 02" or "Buggy 03", where id contains the amount of vehicles created.
#include <iostream>
#include <string>
#include <sstream>
static int id = 0; //Total Number of cars right now
class Car
{
private:
std::string name;
Car()
{
std::ostringstream tmp;
std::string temp;
tmp << "Car" << ++id;
temp = tmp.str();
}
Car(std::string name){this->name=name; id++;}
};
class Turbo : public Car()
{
Turbo():Car()
{
}
Turbo(std::string name):Car(name);
{
}
};
First, let's make sure that the class Car compiles by providing the two required template arguments std::array : type and size. For example: std::array<int, 10>.
The problem is that Turbo needs a valid constructor for its base type Car before it can do anythin else. There are two ways, for it to work:
Either you design Car so that there is a default consructor (i.e.without parameters)
Or you put the constructor for Car in the initialisezer list of the Turbo.
For your edited question, the problem is that the Car constructor must be visible for the derived class, so either public or protected, but not private. You can also use default parameters to get rid of redundant code.
Here a solution:
class Car
{
private:
static int id; //Total Number of cars right now SO MEK IT a static class member
std::string name;
public: // public or protected so that derived classes can access it
Car(std::string n="Car") // if a name is provided, it will be used, otherwhise it's "Car".
{
std::ostringstream tmp;
std::string temp;
tmp << n << ++id;
name = tmp.str(); // !! corrected
}
};
int Car::id = 0; // initialisation of static class member
class Turbo : public Car
{
public: // !! corrected
Turbo(std::string n="Turbo") :Car(n) // !!
{ }
};