Access Child Members Within Parent Class, C++

Access child members within parent class when children are inside a vector of type parent

You just experimented slicing.

A Child is a Parent plus a few more things.

When you try to put a Child in the vector of Parent, only the Parent part of each of these Children is put in the vector (because the vector does not contain Children but Parents); hence the name slicing.

In order to obtain the dynamic polymorphism you are looking for, you need a vector of pointers to Parent; this way, each pointed-to element can be whether a Parent or a Child and behave accordingly.

This is often done with a dynamic allocation of each element in the vector, but this is not mandatory. For example, you could store all the Parents in a vector, all the Children 1 in another, and so on, and finally use a vector of pointers to designate some of them in any order.

If you decide to allocate each Parent/Child individually, you should consider smart-pointers like std::unique_ptr<T> rather than raw pointers and new/delete.

You will find below your example slightly modified in order to obtain dynamic polymorphism.
It relies on dynamic allocation of each element thanks to std::unique_ptr<T>/std::make_unique().

Note that, because of dynamic polymorphism, you need a virtual destructor (even if it does nothing special).
Since this hierarchy of types is intended for dynamic polymorphism, it is encouraged to prevent slicing (that you have just experienced) by forbidding the use of copy/move operations.
Thus, you have to provide one or several constructors that fulfil your needs (but this is quite common).

My last advice is « avoid dynamic polymorphism; prefer template » but it is another topic ;^)

/**
g++ -std=c++17 -o prog_cpp prog_cpp.cpp \
-pedantic -Wall -Wextra -Wconversion -Wno-sign-conversion \
-g -O0 -UNDEBUG -fsanitize=address,undefined
**/

#include <iostream>
#include <string>
#include <vector>
#include <memory> // std::unique_ptr<T>, std::make_unique()

class Parent
{
public:
virtual ~Parent() =default; // ensure correct destruction

// forbid copy and move in order to prevent slicing
Parent(const Parent &) =delete;
Parent &operator=(const Parent &) =delete;
Parent(Parent &&) =delete;
Parent &operator=(Parent &&) =delete;

Parent() =default; // provide a suitable constructor

virtual
const std::string &
getType() const
{
return type;
}
private:
// inline static // is probably better
const std::string type{"parent"};
};

class Child1: public Parent
{
public:
const std::string &
getType() const override
{
return type;
}

private:
// inline static // is probably better
const std::string type{"type1"};
};

class Child2 : public Parent
{
public:
const std::string &
getType() const override
{
return type;
}

private:
// inline static // is probably better
const std::string type{"type2"};
};

int
main()
{
const auto p=Parent{};
std::cout << "p: " << p.getType() << '\n';
const auto c1=Child1{};
std::cout << "c1: " << c1.getType() << '\n';
const auto c2=Child2{};
std::cout << "c2: " << c2.getType() << '\n';
auto people=std::vector<std::unique_ptr<Parent>>{};
for(auto i=0; i<2; ++i)
{
people.emplace_back(std::make_unique<Parent>());
people.emplace_back(std::make_unique<Child1>());
people.emplace_back(std::make_unique<Child2>());
}
for(const auto &e: people)
{
std::cout << e->getType() << '\n';
}
return 0;
}

Access child members within parent class, C++

The only clean way is to use the virtual function approach.

If the Parent class has at least one virtual function (not necessarily DoSomething), there's also a yucky way to do it:

void DoSomething() {
if (Child1* child = dynamic_cast<Child1*>(this)) {
child->childMember = 0;
} else if (Child2* child = dynamic_cast<Child2*>(this)) {
child->childMember = 0;
} // and so on, and so forth
}

(If Parent has no virtual functions, then the dynamic_cast won't work. Though, any class designed to be inherited from should have at least one virtual function, even if it's just the destructor.)

How can I access a child class member stored in a parent class?

root is a Node pointer. root->right is another Node pointer. root->right->down is--you guessed it--a Node pointer.

When you do [...]->value, you're dereferencing that Node pointer, which gives you a Node, and then trying to get the value member on it. But Node has no value member!

You could attempt to cast your Node pointer into an ENode pointer, using dynamic cast. Which would look like:

Node *n = root->right->down;
if(ENode *en = dynamic_cast<ENode*>(n)) {
std::cout << en->value << std::endl;
} else {
std::cout << "That's not an ENode!" << std::endl;
}

But to do this, you'll need to make Node polymorphic (which you can see detailed here).

Also note that in production code, you should be checking to make sure root, root->right and root->right->down are all non-null before going ahead and dereferencing them.

C++ : Access of a child member from a parent class

Not really giving you access to child member, but this is a more OOP approach.

If the only thing you were trying to do is to print the different types of Person classes, then a more proper way of doing it is to define a virtual print function in Person class, then override print function in each child classes, and call person->print() in your Booking class.

In your Person class:

class CPerson
{
public:
virtual void Print()
{
std::cout << Name << "\n";
}
protected:
std::string Name;
}

In your Student class:

class CStudent
{
public:
void Print()
{
CPerson::Print(); // this will execute the Print() you defined in CPerson

std::cout << MatriculationNr << "\n";

// Or you can also just cout all information from here:
// std::cout << Name << ", " << MatriculationNr << "\n";
}
private:
int MatriculationNr;
}

Then in your Booking class, you just call print() from all Person:

void CBookings::Print()
{
for (int i = 0 ; i < Persons.size() ; i++)
{
Persons[i]->Print();
}
}

By doing this, you also don't need to declare Booking as a friend in Person class.


Edit:

In case you were wondering why you want to do it this way:

The fact you used a vector<Person*> implied that there might be other types of Person included in the vector, such as Staff. If not, then you should have just used vector<Student*> instead.

In the case you might also have Staff in it, then doing something like:

std::cout << Persons[i]->MatriculationNr wouldn't make any sense because of course Staff would not have such member in it. Instead, Staff might have a Salary, or whatever in it.

If you keep using the friend class to access private members, you would also need to check each Person's type, if they are a Student or a Staff, then call different cout function based on that.

This becomes tedious if you have many different children types, and your Booking::Print() just becomes a huge if - else if - else if block. And you have to update Booking every time you either change the members of your Person classes, or add another child class to Person.

By having overridden Print() function in your children classes, you don't need to do anything to Booking::Print(), they would all use the same person->Print() from your Booking class.

the child class always have access to the public members of its parent, why and how it is possible?

Using public inheritance, your derived class will have access to protected and public fields and methods declared in the base class. However, your base class doesn't know about your derived class at all. Inheritance only works one way. You basically extend the functionality of a class.

You can think of it as putting a smaller box into a larger one. Each box knows what's inside it, but it doesn't know what's outside of it. The base class is the smaller box, the derived one is the larger box.

How can I access child class version of functions in the parent class from the child class if the objects are in a vector?

If you have a vector of ParentCLass objects, that will hold ParentClass objects. When you add a ChildClass, C++ will need to apply a conversion - push_back takes ParentCLass const&. The conversion found is the standard child to parent conversion; so the parent part is copied.

This is called "slicing". You can create a std::vector<std::unique_ptr<ParentClass>> instead. This won't slice the object, since the vector only holds (smart) pointers to the objects.

Access child class' functions within parent class

You might want to take a look at the visitor pattern.

In essence, the visitor allows one to add new virtual functions to a family of classes without modifying the classes themselves; instead, one creates a visitor class that implements all of the appropriate specializations of the virtual function. The visitor takes the instance reference as input, and implements the goal through double dispatch.

The double dispatch means you are actually calling a virtual function twice: first on the subject which in turn polymorphically calls the visitor.

In your case there is just one method, namely building houses, but you might want to add others later (like drawing them on a screen for example). Given your current example you should add this method to Tile and StreetTile:

virtual void accept(Visitor& v) { v.visit(*this); }

This is the Visitor base class implementation:

class Visitor {
public:
virtual void accept(Tile& t) = 0;
virtual void accept(StreetTile& t) = 0;
};

After that you can implement a Builder class:

class Builder: public Visitor {
private:
int numberOfHouses;
public:
Builder(int n): numberOfHouses(n) {}
virtual void accept(Tile& t) {}
virtual void accept(StreetTile& t) {
t.buildHouses(numberOfHouses);
}
};

After that all you have to do is construct such a builder, and call it on every tile in your vector of tiles:

Builder b(10);
for (Tile tile : tiles) {
tile.accept(b);
}

Is it possible to access child class members that are not in parent class from a parent class type reference variable pointing to child class object?

You are right, you cannot write:

employee.AnnualSalary = 1234;

But this is not your case.

You are just using an object initializer to initialize a FullTimeEmployee object(You have access to all public fields/properties).

Basically you are doing the following:

FullTimeEmployee employeeTemp = new FullTimeEmployee();
employeeTemp .AnnualSalary =2000;
Employee employee =employeeTemp;

Update

I thought one can not typecast parent class object to child class
object since a child can do everything that parent can but vice versa
is not true.

Once again you are right.

And once again this is not your case...

The return type of the method might be Employee but the actual object you return might be something else (a derived class).

In this case you can safely cast the object to your derived type.

Check the following example

namespace CastExample
{
class Program
{
static void Main(string[] args)
{
Employee emp = GetEmployee();
FullTimeEmployee full = (FullTimeEmployee)emp;
System.Console.WriteLine(full.AnnualSalary);
PartTimeEmployee part = (PartTimeEmployee)emp;//InvalidCastException
System.Console.ReadLine();
}

static Employee GetEmployee()
{
return new FullTimeEmployee() { Name = "George", AnnualSalary = 1234 };
}
}
public class Employee
{
public string Name;
}
public class FullTimeEmployee : Employee
{
public int AnnualSalary { get; set; }
}
public class PartTimeEmployee : Employee
{
public int HourlyPay { get; set; }
public int HoursWorked { get; set; }
}
}

And he can access private properties too??

Yes,you can access private fields using reflection

Find a private field with Reflection?

How to get the value of private field in C#?

c# use reflection to get a private member variable from a derived class

Check this :
Why can reflection access protected/private member of class in C#?

@Marc Gravell's answer explain why you can do this but pay special attention to @Tamas Czinege's answer (I quote it here again)

Member accessibility is not a security feature. It is there to protect
the programmer against himself or herself. It helps implementing
encapsulation but it is by no means a security feature.



Related Topics



Leave a reply



Submit