Initialize and modify class variables in derived classes - class

I want to initialize a variable class for my Base class and modify it only in some children classes.
The initialization of this class variable is in the header:
class Base{
public:
Base();
int a = 1;
The header of my derived class is:
class ChildA : public Base{
public:
ChildA ();
int a = 2;
}
Problem
I tried to run this:
Base classe*;
classe = new ChildA();
std::cout << classe->a << std::endl;
The problem is that, instead of printing 2 as I expected, it prints 1 (value initialized in my parent class). For other derived classes, I want classe->a to still return 1.
How can I solve this?

What you are seeing are the results of upcasting - having a base class point to a derived class object.
I highly recommend you read more on the topic, but a simplified picture is that the base class "carries" the whole object (base and derived content), but can access only it's original, own content. This is why you see a value from the base class rather than the derived class.
Lippman's C++ Primer has a very comprehensive explanation of upcasting, downcasting, object slicing, and other inheritance-related concepts. This includes implementing virtual functions which give you the functionality to invoke derived class functions through an interface that's common with base.

|----------------|-----------------|
| a (for Base) | a (for ChildA) |
|----------------|-----------------|
\________________/
^
|_ classe
Sorry if my drawing is not that good! As you can see in the above picture, when you create an object of type ChildA, this object contains a part for keeping the data members of the base class (i.e. Base) and another part for the data members of derived class (i.e. ChildA). Considering the fact that you have a pointer to the base class (i.e. classe), this pointer only allows you to access the base member variables and methods. So calling classe->a, returns the Base::a for you, that is 1.
If you change the type of classe pointer into ChildA, in that case calling classe->a will return 2, because it refers to the a inside the derived class, i.e. ChildA::a.
For other derived classes, I want classe->a to still return 1. How can
I solve this?
If you need in some derived classes to access different as, it is better to have a virtual function in the base class and override the base function if needed:
class Base {
public:
Base() {}
virtual int getA() { return a; }
private:
int a = 1;
};
class ChildA : public Base
{
public:
ChildA() {}
int a = 2;
};
class ChildB : public Base
{
public:
ChildB() {}
int getA() { return a; }
private:
int a = 2;
};
Now by calling getA() on a pointer of Base or ChildA, you will have 1, but calling getA on an object of type ChildB will return 2.

Related

Converting UML to code c++. Problem with inheritence. Do constructors of all classes run when object of any one of them is created?

I have this UML diagram
Ad this is the corresponding C++ code
//Parent class Flight
class Flight
{
private:
int callNumber;
Airplane plane;
vector<Passenger> passengers;
public:
//Constructor
Flight();
//Functions
int getCallNum();
void setCallNum();
Airplane getPlane();
//What parameters are taken in these functions.
//I know they are of type Airplane and passenger but are they vectors?
void setPlane(Airplane);
void addPassenger(Passenger);
void removePassenger(Passenger);
};
//Airplane class, child of Flight
class Airplane : public Flight
{
private:
int firstClassSeats;
int economySeats;
public:
//Constructor
Airplane();
//Functions;
int getFirstClassSeats();
int getEconomySeats();
void setFirstClassSeats();
void setEconomySeats();
};
//Passenger class, child of FLight
class Passenger : public Flight
{
private:
string name;
int age;
string address;
public:
//Constructor
Passenger();
//Functions
string getName();
int getAge();
string getAddress();
void setName(string);
void setAge(int);
void setAddress(string);
};
I wonder:
do constructors of all classes run when an object of either parent or base class is created?
Can base class access functions or data of child classes?
I do not know how set plane function in parent class would look like. Would it take an object of type Airplane as an argument? Similarly, will addpassenger function in parent class take a vector of type Passenger as an argument?
In short
If A inherits B (or A specializes B), then you should be able to say A is a (kind of) B. When in doubt, prefer object composition over inheritance.
More details
The parameters taken by the member functions, are the parameters that you indicate for the operations in the diagram. No parameter in the diagram leads to no parameters in the code.
The inheritance here is ambigous. There is no inheritance in your diagram. There is some in your code, but it does not make so much sense: is a passenger really a flight? E.g. can a passenger fly, have a crew, etc.?
If the inheritance would be suitable, as a general rule in C++: the constructor of an object is always called when the object is created. In case of inheritance, all the constructors of the class hierarchy are invoked, starting with the base constructor, until the most derived constructor (the rules can be more tricky, for example in case of multiple inheritance). In UML, the rules on constructors are not fully specified as far as I know.
By default, a class can only access public members of another class. If a class is derived from a base class (in UML: if a class is a specialisation of a more general class), the derived class has only access to the public and protected members of the base class. Try to avoid protected, since it's a frequent cause of nasty bugs.
WHen implementing in C++ an UML class diagram, there is a tricky issue about the types of the properties and arguments, because C++ has a value semantic: if you pass an Airplane as argument, the original airplane object is copied. Same if you have an Airplane property. However, in UML, properties and associations have a reference semantic (except for datatypes), meaning that the airplane argument would still refer to the same original airplane. So in your specific case, you'd probably want to pass a reference or a (smart) pointer to an Airplane.

What do I need to do in order to ask, if an pointer to an abstract class in instance of a child class?

I need some help to understand everything correctly.
I want to check a pointer to a abstract class if it is instance of a specific child class.
I have one abstract class "kunde" and two child classes "firmenkunde" and "privatkunde" who inherit the methods of kunde.
In order to search by "int knr" (int customer number) I use as return type a pointer to "kunde".
Within the database class I get back the "kdstatus" and use
kunde * kd = new privatkunde(0);
if the status is PK or new firmenkunde(0) if it would be FK.
The abstract class kunde doesn't have any attribute I could use to save the status.
This way I did hope to be able to ask, if the returned pointer would be an instance of the class privatkunde or firmenkunde. But I did not found any method to do this.
MessageBox::Show(marshal_as<String^>(typeid(kd).name()));
I did ask the typeid name but this only returns "class kunde *" and is not what I want to know.
Is there a way to work around this problem?
You can use typeid as you mentioned. Using the polymorphism, you can write:
kunde * kd = new privatkunde(0);
if(typeid(kd) == typeid(privatkunde))
{
// This is a privatkunde objet
}
See here to have more explanation.
The problem you encounter is that your kunde class is not polymorphic. As commented by #George, see how the virtual methods work.
I hope it can help.
Generally you can use dynamic_cast for this.
An example:
class Parent
{
public:
virtual ~Parent();
virtual void do_thing()= 0;
};
class Child1: public Parent
{
public:
void do_thing() override
{
//...
}
};
class Child2: public Parent
{
public:
void do_thing() override
{
//...
}
};
void use_parent(Parent* p)
{
auto c1_ptr = dynamic_cast<Child1*>(p);
if(c1_ptr != nullptr)
{
// p is a Child1
do_thing_with_child1(c1_ptr);
}
auto c2_ptr = dynamic_cast<Child2*>(p);
if(c2_ptr != nullptr)
{
// p is a Child2
do_thing_with_child2(c2_ptr);
}
}
While this works, it becomes difficult to maintain if you have multiple child classes. You have to remember to add a case for each new child class you define.
A better way to structure something like this would be to use the "Tell, don't ask" concept when designing your object-oriented systems. A great write-up on this concept can be found here.

Interface pointers C++

I can't express my question in words. Please look the code below, I hope you will understand my question.
I have a class and an interface as shown below.
class MyInterface
{
public:
virtual ~MyInterface(){}
virtual void print() = 0;
};
class MyClass : public MyInterface
{
public:
MyClass(){}
~MyClass(){}
void print()
{
printf("Hello World\n");
}
};
Now here's my question.
MyClass* myclass = new MyClass();
myclass->print(); //will print "Hello World"
MyInterface* pMyInterface = (MyInterface*)myclass;
pMyInterface->print();
Will the second call print Hello World as well? If yes, then why?
One note is that you do not need to explicitly cast to an accessible base class, like you do in MyInterface* pMyInterface = (MyInterface*)myclass;. It is an implicit conversion from a pointer/reference to a derived class to that of an accessible base class.
In fact, such casting may introduce bugs if the classes are unrelated.
Find more details in virtual function specifier.

copy constructor copy pointer to abstract class

Say I have a class General, which holds a pointer to an abstract class, *_abstract.
If I want to implement General copy constructor, how is it done?
I try this but it fails:
General::General(const General &other)
{
*_abstract = *other._abstract;
}
I also tried:
General::General(const General &other)
{
*_abstract = new Abstract();
*_abstract = *other._abstract;
}
which is impossible because of the abstract class initialization (no constructor)
If you need to deep copy the abstract class then add a virtual clone function to the abstract class and copy it with that.
understanding virtual copy constructors

Access specifiers in class

I know that, normally, 'objects' of a class cannot access the private members. But in the function definition of a copy constructor, you use objects to access the private members members. How come?
eg:-
class Sample {int i,j;
public:
Sample(int a, int b)
{i=a;j=b;}
Sample(Sample &S)
{j=s.j;i=s.i;}
}
It is the same class. A different instance, but the same class.
private means that the member is only visible within the class - including other instances.