Access default declared content from inherited class - c++

I'm trying to make an inherited class access the self class default content.
The code is below (Note that array declared isn't the same size between parent and child class)
#include <iostream>
class A {
public:
int number[2] = {1,2};
A(){};
void show() {std::cout << "Number: " << number[0] << ", " << number[1] << "\n"; };
};
class B : public A {
public:
int number[3] = {5,6,7};
B() {};
// With this code below it works but I don't want to code the same function on every child class
//void show() {std::cout << "Number: " << number[0] << ", " << number[1] << "\n"; };
};
int main() {
A obj_a;
obj_a.show();
B obj_b;
obj_b.show();
}
Which outputs this:
Number: 1, 2
Number: 1, 2
Expected output should be:
Number: 1, 2
Number: 5, 6
Anyone can help?
Note: The code should be used on arduino, I used std::cout just for sharing to you.
EDIT:
I want to make an array of objects so it can be easily changed the size, and in other parts of the code, I can simply for loop of the array and do whatever is needed.
Also the purpose for subclasses is because I have different "numbers" and his sizes. For example, imagine a vehicle which is the super class, that has 2 child classes named "auto" and "moto", auto has int wheels[4] = {...} and moto int wheels[2] = {...}

A::number and B::number are two completely independent class members, that have nothing to do with each other.
A::show() only knows about members of A, and only knows about A::number. It doesn't know anything about B even if it's a superclass of an instance of B.
Your C++ textbook will explain what virtual functions are, and how to use them. The simplest solution is to add a virtual method in A, let's call it get_number, that returns an int *, and the get_number function simply returns number:
class A {
// ...
virtual int *get_number()
{
return number;
}
};
In B the virtual function gets overridden, and it returns a pointer to its own class's number.
class B {
// ...
int *get_number() override
{
return number;
}
};
Then, your show() method calls get_number() to get a pointer to the appropriate array. See your C++ textbook for a complete discussion of virtual class methods.

You are experiencing name hiding - name in inner scope shadows the same symbol name in outer scope. In your case B::number hides A::number.
C++ does not support "virtual" member variables, so you cannot redefine number. My suggestion is to not use inheritance if there should indeed be just one array. Because then B is not really an A.
Or at least you could generalize the A class to contain arbitrarly long array. There are multiple ways doing that:
std::vector A::number member with a constructor A(std::size_t n) accepting the size.
Make A a class template with template<std::size_t N> argument denoting the size, then you can use std::array<int,N> number; member variable.
Pass the array to the base class for ownership.
Another option is to make show virtual and override it in the derived class with custom printing, but then you will still be left with two arrays, which is a clear design flaw.

Related

Derived Get/Set Methods

Imagine I have this code:
class A {
public:
void GetInt() { cout << number << endl; }
void SetInt(int n) { number = n; }
private:
int number = 0;
};
class B : public A {
public:
void GetInt() { cout << number << endl; }
private:
int number = 0;
};
int main() {
B b;
b.SetInt(5);
b.GetInt(); // Prints 0, needs to be 5
return 0;
}
Is there any way to make SetInt() changing B.number without implementing it in B? Imagine I have 500 derived classes from A, and they set their number in the same { number = n; }. Do I have to implement the same SetInt() method 500 times?
The simple way to get what you ask for is this:
class A {
public:
void GetInt() { cout << number << endl; }
void SetInt(int n) { number = n; }
private:
int number = 0;
};
class B : public A {
// don't hide methods inherited from A
// don't add members that are already present (as private member of A)
};
int main() {
B b;
b.SetInt(5);
b.GetInt(); // Prints 5
return 0;
}
Private members are inherited, they just cannot be accessed directly. Though as A does provide public accessors, B has acess to A::number via the setter from A.
PS A method called Get___ should actually return something, not just print the value on the screen.
No, 0 is the correct result. In your class B you create a whole new member B::number which is independent from A:::number. So when you run A::SetInt, that member function changes A::number and when you run B::GetInt, that function accesses A::number which was never set to 5.
Try not to have members in derived types that have the same name as a member in the base class. All it does is create confusion.
In case you really want each derived class to yield and handle its own value in terms of class hierachy separation - which I'd find at least questionable at all in terms of design and problem solution approach - you cannot avoid a minimum amount of code duplication for each derivation. At least you need the member access itself to be duplicated. There are some template/macro tricks to circumvent code explosions here (generic member instrusion), but since I really don't think, that this is what you want to achieve, I do not go into details for now.
Otherwise, idclev 463035818's answer is the way to go.

how to calculate member offset in c++ class

example
class B {
public:
int y;
private:
int x;
};
class A : public B {
public:
int a;
private:
int b;
};
how to calculate A.b's offset in some object of A ?
one method was to use gdb, but it was slow.
is there other method works which don't need to execute/compile the program ?
how to calculate A.b's offset in some object of A ?
You can use the standard macro offsetof if the class is standard layout, or your language implementation supports it for non-standard layout classes (your class is not standard layout):
std::size_t offset = offsetof(A, b);
is there other method works which don't need to execute/compile the program ?
You could read the ABI specification of your language implementation. If you understand all of it, the calculation should be possible with basic addition and multiplication.
The simple cases are easy to calculate. The rules can be quite complex however and it may not be easy to accurately identify the cases which are simple.
Member's offset equals to
ptrdiff_t(&obj.member) - ptrdiff_t(&obj)
or inside of class' method, especially if your member is private, you may use
ptrdiff_t(&this->member) - ptrdiff_t(this)
The only thing to take into account is if there are virtual methods then members offsets are not 0-based. At 0-th offset there is usually pointer to virtual methods table. If there are no virtual methods then offsets are 0-based (0 is offset of first member of most base parent class), at least I never had non-0-based offsets for non-virtual classes.
Full example code:
Try it online!
#import <iostream>
#import <cstddef>
using namespace std;
class B {
public:
int y;
private:
int x;
};
class A : public B {
public:
int a;
ptrdiff_t off_b() const { return ptrdiff_t(&this->b) - ptrdiff_t(this); }
private:
int b;
};
int main() {
A obj;
cout << obj.off_b() << endl;
cout << ptrdiff_t(&obj.a) - ptrdiff_t(&obj) << endl;
cout << ptrdiff_t(&obj.y) - ptrdiff_t(&obj) << endl;
return 0;
}
Output:
12
8
0
Here is same code but with virtual methods. Members start at offset 8 inside this code run, but this offset may differ in different implementations.

Flawed inheritance when children classes need to include each other in c++

Say I have a class A. Class B and class C are both children classes of A.
Would it be a flawed inheritance design if the class C needed to include B?
edit: an example
Say I have a parent class called Trip that has two attributes : start and end. My first inherited class (B) from A is called SimpleTrip, it has an added attribute called transport (so in total : start, end and transport). My second inherited class (C) from A is called CompoundTrip, it has two added attributes an array of SimpleTrips and a number of trips (so it total : start, end, array of SimpleTrips, number of trips). A compound trip is a "group" of simple trips, but is still a trip.
Have a look at this and try to answer "What does c.a() print" without running the program, then try and run it.
#include <iostream>
struct A {
virtual void a() {
std::cout << "a" << std::endl;
}
};
struct B : A {
virtual void a() override {
std::cout << "b" << std::endl;
};
};
struct C : A, B {
};
int main() {
C c;
c.a();
}
https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem

Do I need to initiate parent class or just child class

I am new in programing and I am analyzing code with parent class fruit and child classes apple and pear. In this example there is pointer to parent class. After I extended this code I find out that using object I can access parent public members and all child members. Question is why do I need those pointers?
// are this pointer needed since I can use j.setWeight(11)
#include <iostream>
using namespace std;
class fruit {
private:
int weight;
public:
void setWeight(int x)
{
weight = x;
}
int getWeight()
{
return weight;
}
};
class apple : public fruit {
public:
void eat()
{
cout << "Now I am eating apple"
<< "=" << getWeight() << endl;
}
};
class pear : public fruit {
public:
void eat()
{
cout << "Now I am eating pear"
<< " = " << getWeight() << endl;
}
};
int main()
{
apple j;
pear k;
fruit* fruit1 = &j;
fruit* fruit2 = &k;
k.setWeight(5);
k.eat();
fruit1->setWeight(11);
apple apple;
apple.postaviTezinu(16);
apple.jelo();
return 0;
}
are this pointers needed since I can use j.setWeight(11) and results is same as
fruit1 -> setWeight(11) ... what s difference, thx
I suspect that the code you are looking at was written to demonstrate how pointers to base classes can be used with objects of derived classes. No, pointers are not necessary for the functionality of this learning exercise. In fact, that is probably the reason this functionality was chosen. Since you see how to accomplish the same thing without pointers, it should be easier for you to relate pointers to what you already know.
The key learning points I see in this exercise are
The same pointer type (fruit *) can point to objects of different types (apple or pear).
When using the pointer to the base class, you can access base class members.
When using the pointer to the base class, you cannot access derived class members. (Implied by omission; compare what is done with k to what is done with fruit1.)
You will need to move on to the more advanced lessons to learn when pointers are more useful than accessing objects directly (probably after eat() is turned into a virtual function). For now, just learn how the same task can be accomplished by different means.
(Sure, you could get that information here, but that code looks like it's part of a series. Continuing with that series might be the better way to learn.)
Since you're new to programming, learning polymorphism may be a bit advanced for you at this stage. To answer your question directly: No, you don't need pointers in your example code, and they are in no way helpful.
However, pointers to objects are often useful for:
Reducing unnecessary copying of objects
In the case of polymorphism (as in your example) pointers help in sections of your programme where you don't know which object type you're dealing with, or don't want to have to deal with them in different ways
Example:
#include <iostream>
#include <vector>
class A
{
public:
virtual void foo ()
{
std::cout << " I am A\n";
}
};
class B : public A
{
public:
virtual void foo ()
{
std::cout << " I am B\n";
}
};
void bar ( const std::vector <A*> & obj )
{
// Here it outputs the foo () function that is
// appropriate for the class
for ( unsigned int i = 0; i < obj . size (); ++i )
obj [i] -> foo ();
}
int main ()
{
A a1, a2, a3;
B b1, b2, b3;
// the below input style requires C++11,
// otherwise input them one-by-one
std::vector <A*> array {&a1, &b1, &a2, &a3, &b2, &b3};
bar ( array );
return 0;
}
The above array can store any A objects, including the inherited objects (it can't do this without pointers); and the bar function can still perform operations on the elements in the array without needing to know which object type they belong to within the inheritance tree (due to the virtual function). This is crucial for taking advantage of polymorphism, and saving on repetition of functions and code in general.

How to elegantly slice the object

So basically I have a class SomethingSwimming and a derived class Ship. I want to implement that upon some event a Ship may lose its special qualities (such as holding lobsters hostage) and become just another SomethingSwimming object.
To illustrate:
class SomethingSwimming
{
protected:
int m_treasures;
public:
SomethingSwimming(int treasures): m_treasures(treasures) {;}
virtual int howManyLobstersOnBoard() {return 0; }
};
class Ship: public SomethingSwimming
{
protected:
int m_lobstersOnBoard;
public:
Ship(int treasures, int lobstersOnBoard): SomethingSwimming(treasures), m_lobstersOnBoard(lobstersOnBoard) {;}
int howManyLobstersOnBoard() {return m_lobstersOnBoard; }
};
void crash(shared_ptr<SomethingSwimming>& b)
{
b = make_shared<SomethingSwimming>(100);
}
int main()
{
shared_ptr<SomethingSwimming> a = make_shared<Ship>(100, 12);
cout << "How many lobsters on board: " << a->howManyLobstersOnBoard() << endl;
crash(a);
cout << "How many lobsters on board: " << a->howManyLobstersOnBoard() << endl;
return 0;
}
My question is how to crash the Ship so it becomes only SomethingSwimming (so it's not a Ship anymore) without reinitializing.
There is no way of cutting away rest of the object while keeping the identity of the base sub object. You can make a new copy of the base sub object, and throw away the derived object.
Currently you create an unrelated object in crash and thereby m_treasures won't be affected by m_treasures of the previously pointed object. To create a copy of the original base sub object, you can do:
b = make_shared<SomethingSwimming>(*b);
Alternatively, at the call site you can treat an indirectly referred base as if it were not part of a derived object by calling virtual member functions statically:
a->SomethingSwimming::howManyLobstersOnBoard()
This will result in the value of m_treasures regardless of the most derived type of the object.