Why is this program of hybrid inheritance giving wrong output? - c++

In this program, I am trying to inculcate hybrid inheritance in this program but this is giving wrong output. I have taken arithmetic as base class and add,sub,mul,div as its derived classes.
And then I have derived a class result using add,sub,mul,div as base classes. I have tried all the data types but with all it gives wrong or zero output.
#include "iostream"
using namespace std;
class arithmetic
{
public:
float var1,var2;
void introduce()
{
cout<<"This program will perform arithmetic on two variables"<<endl
<<"Enter the first variable: ";
cin>>var1;
cout<<"Enter the second variable: ";
cin>>var2;
}
};
class add:public arithmetic
{
protected:
float res_add;
public:
void show_add()
{
res_add=var1+var2;
cout<<"Addition of those variables gives "<<res_add<<endl;
}
};
class sub:public arithmetic
{
protected:
float res_sub;
public:
void show_sub()
{
res_sub=var1-var2;
cout<<"Subtraction of those variables gives "<<res_sub<<endl;
}
};
class mul:public arithmetic
{
protected:
float res_mul;
public:
void show_mul()
{
res_mul=var1*var2;
cout<<"Multiplication of those variables gives "<<res_mul<<endl;
}
};
class div:public arithmetic
{
protected:
float res_div;
public:
void show_div()
{
res_div=var1/var2;
cout<<"Divison of those variables gives "<<res_div<<endl;
}
};
class result:public add, public sub,public mul,public div
{
public:
void showres()
{
cout<<"Arithmetic on the given two varibales gives us the following result:"<<endl;
}
};
int main()
{
result example;
arithmetic var;
var.introduce();
example.showres();
example.show_add();
example.show_sub();
example.show_mul();
example.show_div();
return 0;
}

You are creating two separate object var (base class object) and example ( derived class object). Initializing the var1 and var2 by calling the var.introduce() and calling the methods show_add(), show_sub() etc. in the example object, in example object var1 and var2 is not initialized. so whatever arithmetic operation you are calling is getting applied in the uninitialized var1 and var2 member variable of example object.
you don't need to create the base class object(var). call the intruduce() method from the example then it will start working fine.
Please go through the below sample code to understand the concept of virtual base class.
#include <iostream>
class A
{
public:
int i;
};
class B : virtual public A
{
public:
int j;
};
class C: virtual public A
{
public:
int k;
};
class D: public B, public C
{
public:
int sum;
};
int main()
{
D ob;
ob.i = 10; //unambiguous since only one copy of i is inherited.
ob.j = 20;
ob.k = 30;
ob.sum = ob.i + ob.j + ob.k;
std::cout << "Value of i is : "<< ob.i<<"\n";
std::cout << "Value of j is : "<< ob.j<<"\n";
std::cout << "Value of k is : "<< ob.k<<"\n";
std::cout << "Sum is : "<< ob.sum <<"\n";
return 0;
}
Output:
Value of i is : 10
Value of j is : 20
Value of k is : 30
Sum is : 60
Live Demo on coliru

If you want to avoid virtual inheritance and want something simpler, use composition.
For this, class result should contain objects of add, sub, mul and div.
The resulting code for result will look something like this:
class result:public arithmetic
{
public:
mul m;
add a;
sub s;
div d;
void assignvals()
{
m.var1 = var1; m.var2 = var2;
a.var1 = var1; a.var2 = var2;
s.var1 = var1; s.var2 = var2;
d.var1 = var1; d.var2 = var2;
}
void showres()
{
cout<<"Arithmetic on the given two variables gives us the following result:"<<endl;
}
};
The resulting code for main will look something like this:
int main()
{
result example;
example.introduce();
example.assignvals();
example.showres();
example.a.show_add();
example.s.show_sub();
example.m.show_mul();
example.d.show_div();
return 0;
}
Note: Some compilers will complain if div is used as a class name because it is also the name of a library function in C++. So you will have to change the name of this class.

Related

Use default value of Subclass method in an array of Base class

Is there any way that cout << a[0]->function(); can give a 5 instead?
At the moment, it takes the default value of the base class and runs the method of the subclass.
But I want it to run the method of the subclass and take the default value of the subclass.
class Basis
{
public:
virtual int function(int i = 1) { return 2; }
};
class Sub : public Basis
{
public:
int function(int i = 5) override { return i; }
};
int main()
{
Basis* a[2];
a[0] = new Sub();
cout << a[0]->function(); //gives 1
}
Your code is calling function() via a Basis* pointer, so it is going to use the default value defined by Basis, there is no way for Sub to override that. Calling function() via a Sub* pointer would use the default value defined by Sub instead.
So, given the code you have shown, the easiest way I can think of doing what you are asking for is to use function overloads, eg:
class Basis
{
public:
virtual int function() { return function(1); }
virtual int function(int i) { return 2; }
};
class Sub : public Basis
{
public:
int function() override { return function(5); }
int function(int i) override { return i; }
};
int main()
{
Basis* a[2];
a[0] = new Basis();
a[1] = new Sub();
cout << a[0]->function(); //gives 2
cout << a[1]->function(); //gives 5
}

how to turn this piece of code into static polymophism?

I am trying to study static polymophism and I implemented the following code. Thanks to the comments from StackOverflow members, I came to understand that what I just wrote is not static polymophism, but actually template-based policy-pattern.
Can anyone give any insight about how to turn this piece of code into static polymophism?
#include <iostream>
template<typename T>
class Interface {
T ex;
public:
double getData() {
return ex.getData(0);
}
};
class Extractor1 {
public:
double getData(const int a) {
return 1;
}
};
class Extractor2 {
public:
double getData(const int a) {
return 2;
}
};
int main() {
// here is the problem: the following 2 variables belong to different types. Therefore, I cannot create an array of pointers which point to the base class
Interface<Extractor1> e1;
Interface<Extractor2> e2;
std::cout<<"FE1 "<< e1.getData() <<" FE2 "<< e2.getData()<<std::endl;
return 0;
}
You can change your code like this to achieve static polymorphism:
#include <iostream>
template <typename T>
class Interface {
public:
double getData(int a) {
return static_cast<T *>(this)->getData(a);
}
};
class Extractor1 : public Interface<Extractor1> {
public:
double getData(int a) {
return 1;
}
};
class Extractor2 : public Interface<Extractor2> {
public:
double getData(int a) {
return 2;
}
};
int main() {
Interface<Extractor1> e1;
Interface<Extractor2> e2;
std::cout << e1.getData(1) << " " << e2.getData(2) << std::endl;
}
The advantage of using static polymorphism is you avoid paying the runtime cost of a vtable lookup like you would when using virtual functions. The drawback though, as I see you are running into based on your 'array' comment, is that you cannot place these different Extractor classes into an array or any other container, because they are both inheriting different base types. The only way around this, aside from using something like a tuple or a container filled with boost::any types, is creating a common base class for your Extractor classes.

Can I use polymorphism to store different objects in an array with C++?

Im learning C++, and I am trying to do a little app. My app takes an informal ticket (without TAX) like this:
2
3 Mi_primera_tablet 7.95
1 El_general_en_su_laberinto Gabriel_García_Márquez 23.50
Where the first line is the number of items
In the second and third line= type of tax + title + price without TAX
The items can be of different types: books(TAX type 3), toys(TAX type 1)
All types inherit from the class article, but depending of the TAX type the price will be different (polymorphism).
I need to store all items (different types) in an array, how can I do it?
You can store pointers in the array.
Exapmle (c++11):
#include <iostream>
#include <vector>
#include <memory>
struct A {
int value;
};
struct B {
double item;
};
class Element {
public:
explicit Element(A a);
explicit Element(B b);
const A * AsA() const;
const B * AsB() const;
private:
class AbstractElement {
public:
virtual ~AbstractElement() {
}
protected:
AbstractElement() {
}
};
template <typename T>
struct ConcreteElement : public AbstractElement {
T body;
explicit ConcreteElement(T input_body)
: body(std::move(input_body)) {
}
};
std::unique_ptr<AbstractElement> element_;
};
Element::Element(A a)
: element_(new ConcreteElement<A>(a)) {
}
Element::Element(B b)
: element_(new ConcreteElement<B>(b)) {
}
const A * Element::AsA() const {
const auto concrete_element =
dynamic_cast<ConcreteElement<A> *>(element_.get());
return concrete_element ? &(concrete_element->body) : nullptr;
}
const B * Element::AsB() const {
const auto concrete_element =
dynamic_cast<ConcreteElement<B> *>(element_.get());
return concrete_element ? &(concrete_element->body) : nullptr;
}
int main() {
std::vector<Element> values;
values.push_back(Element(A{1}));
values.push_back(Element(B{1.5}));
values.push_back(Element(A{-5}));
values.push_back(Element(B{0}));
for (const auto & element : values) {
const auto p_a = element.AsA();
if (p_a) {
std::cout << "A: " << p_a->value << std::endl;
} else {
const auto p_b = element.AsB();
std::cout << "B: " << p_b->item << std::endl;
}
}
return 0;
}
output:
A: 1
B: 1.5
A: -5
B: 0
Maybe you can try boost::variant library, it act as a wrapper around anything. then you can store many boost::variant wrapper in an array
if I understood your question correctly, you need to know how to define an array of your base class with it's derived classes. If this is the case, you can do it by defining an array in the base class, which in your case would look something like this:
article ArrayName [n];
Books Books = new Books();
//do some thing with the books object
ArrayName[0] = Books;
All types inherit from the class article, but depending of the TAX
type the price will be different (polymorphism).
type or TAX type could be stored as a member in Class article.
No polymorphism is needed here.
The items can be of different types: books(TAX type 3), toys(TAX type
1)
Or you could store only the type (books, toys), and do a lookup in a table type | TAX-type, if the TAX types will always be the same for the full range of each type.
But if you really have or need a derived class for each type (for example to store different properties), you could call a virtual function in the derived classes CalcTax() for example.
An array with (baseclass*) pointers to the items could be created, and you can loop through that array, and call CalcTax() on each item, which will call the correct virtual function.
For example:
#include <iostream>
class Base
{
public:
virtual CalcTax() = 0;
};
class Type_1 : public Base
{
public:
virtual CalcTax() {std::cout << "Type_1\n";}
};
class Type_2
{
public:
virtual CalcTax() {std::cout << "Type_2\n";}
};
int main()
{
Base *arrItems[2]; // or better use std::vector<> etc.
Type_1 t1; // just a quick demo of polymorphism
Type_2 t2;
arrItems[0] = (Base*)&t1;
arrItems[1] = (Base*)&t2;
for (int i = 0; i < 2; ++i) {
arrItems[i]->CalcTax();
}
return 0;
}

How to transfer values set in privates of base class by an object of one derived class to an object of another derived class?

I have my main.cpp like this:
#include <iostream>
#include "curve1.h"
#include "curve2.h"
using namespace std;
int main()
{
Curve1 curve1Obj;
Curve2 curve2Obj;
curve1Obj.enterScores();
curve1Obj.calcAverage();
curve1Obj.output();
curve1Obj.curve();
curve1Obj.output(curve1Obj.new_getAverage1(), curve1Obj.new_getScore1());
curve2Obj.curve();
return 0;
}
Base class Score has two derived classes Curve1 and Curve2. There are two curve() functions, one is in Curve1 and other in Curve2 classes. getSize() returns the value of iSize.
My base class header score.h looks like this:
#ifndef SCORE_H
#define SCORE_H
class Score
{
private:
int *ipScore;
float fAverage;
int iSize;
public:
Score(
void enterScores();
void calcAverage();
void output();
void output(float, int*);
void setSize();
int getSize();
void setScore();
int *getScore();
float getAverage();
};
#endif
You can see that I have used curve1Obj to enter scores, calculate average and output. So if I call getSize() function with cuve1Obj, it gives the right size that I took from user in enterScores() function. Also the result is same if I call getSize() in score.cpp definition file in any of the functions (obviously).
.....
The problem is when I call curve() function of Curve2 class in main (line 23) with the object curve2Obj, it creates a new set of ipScore, fAverage and iSize (i think?) with garbage values. So when I call getSize() in curve() definition in curve2.cpp, it outputs the garbage.
.....
How can I cause it to return the old values that are set in curve1.cpp?
Here is my curve2.cpp
#include <iostream>
#include "curve2.h"
using namespace std;
void Curve2::curve()
{
cout << "getSize() returns: " << getSize() << endl; // out comes the garbage
}
Can I use a function to simply put values from old to new variables? If yes then how?
Well, basically your problem can't be easily solved the way it is.
Like you said:
1 - Don't use constructors of any type.
2 - Don't use vectors.
3 - Using dynamic new and delete etc. etc.
Use the constructors or stick with what G. Samaras and Richard Hodges said. You can only solve this that way.
There is limited information available here but I would say that your Score constructor has not initialised ipScore or iSize.
If you are hell-bent on using a pointer to a dynamically allocated array of ints for your score then at least null out the pointer in the constructor and test for null in the average function (i.e. no scores yet).
Better yet... use a std::vector of int for your scores.
Why are people still using new and delete? What the hell are they teaching in schools?
What I think you want is this:
#include <vector>
class Score {
public:
Score()
: _scores()
, _average(0)
{ }
void calcAverage() {
double total = 0;
if(auto s = _scores.size() > 0) {
for (const auto& v : _scores)
total += v;
total /= s;
}
_average = total;
}
virtual void curve() = 0;
protected:
// one of the few correct uses of 'protected' - giving limited access to data as interface to derived classes
const std::vector<double>& scores() const {
return _scores;
}
// or
std::vector<double> copyScores() const {
return _scores;
}
private:
// use doubles since you'll be doing floating point arithmetic
std::vector<double> _scores;
double _average;
};
class Curve1 : public Score {
public:
virtual void curve() override {
// custom curve function here
// written in terms of scores() or copyScores() if you want to make changes to the array
}
};
class Curve2 : public Score {
public:
virtual void curve() override {
// custom curve function here
// written in terms of scores();
}
};
You need to understand inheritance. Curve1 inherits from Score. Curve2 inherits from Score.
Now see this example:
#include <iostream>
class Base {
int x;
};
class A : public Base {
int a;
public:
void set_a(int arg) {
a = arg;
}
int get_a() {
return a;
}
};
class B : public Base {
int b;
public:
void set_b(int arg) {
b = arg;
}
int get_b() {
return b;
}
};
int main() {
A a_object;
a_object.set_a(4);
B b_object;
b_object.set_b(a_object.get_a());
std::cout << "a of a_object = " << a_object.get_a() << "\n";
std::cout << "b of b_object = " << b_object.get_b() << "\n";
return 0;
}
class A, has as members x and a. Class B has as members x and b.
When I create an instance of class A, I will two data members created internally, x and a.
When I create an instance of class A, I will two data members created internally, x and b.
But, the first x and the second are DIFFERENT. They are a different cell in the memory!
something like this:
class Score {
public:
Score()
: _scores(0)
, _size(0)
, _average(0)
{ }
// copy constructor
Score(const Score& rhs)
: _scores( new double[rhs._size] )
, _size(rhs._size)
, _average(rhs._average)
{
if (_size) {
for(int i = 0 ; i < _size ; ++i) {
_scores[i] = rhs._scores[i];
}
}
}
// ... and if copy constructor then always a copy operator
Score& operator=(const Score& rhs) {
// assignment in terms of copy constructor - don't repeat yourself
Score tmp(rhs);
swap(tmp);
return *this;
}
// pre c++11 we make our own swap.
// post c++11 we would make non-throwing move constructor and move-assignment operator
void swap(Score& rhs) {
// std::swap is guaranteed not to throw
std::swap(_scores, rhs._scores);
std::swap(_size, rhs._size);
std::swap(_average, rhs._average);
}
~Score()
{
delete[] _scores;
}
void calcAverage() {
double total = 0;
if(_size > 0) {
for (int i = 0 ; i < _size ; ++i)
total += _scores[i];
total /= _size;
}
_average = total;
}
virtual void curve() {};
private:
// use doubles since you'll be doing floating point arithmetic
double * _scores;
int _size;
double _average;
};
// rmember to override the copy operators and assignment operators of derived classes
// remember to call the base class's operator

How to get instance of nested class in C++

I have the following code:
class outer
{
struct inner
{
int var1;
int var2;
inner() { var1 = 1; var2 = 2; }
};
inner inner_instance;
public:
const inner *get_inner() { return &inner_instance; }
};
int main(int argc, char *argv[])
{
// 1
outer outer_instance;
cout << outer_instance.get_inner()->var1 << endl;
// 2
// this cannot be compiled because outer::inner is private
//const outer::inner *inner_ref = outer_instance.get_inner();
//cout << inner_ref->var1;
// 3
const int *inner_var2 = (int *) outer_instance.get_inner();
inner_var2++;
cout << *inner_var2 << endl;
return 0;
}
I understand why No.2 cannot be compiled. I just do not know what is the design idea of the compiler that allows access to the public fields of a private nested class but not the nested class itself, like No.1. The instance data is still in the memory. If I know the structure of such private nested class, I can still achieve assigning like No.3 does.
Does that mean it is better not to return pointer or reference of a private nested class in a public function? And if I really have to return something about the nested class to the outer world, make it public?
Thanks!
Put the struct inner definition in the public if you want to use it outside outer class.
class outer
{
public:
struct inner
{
int var1;
int var2;
inner() { var1 = 1; var2 = 2; }
};
private:
inner inner_instance;
public:
const inner *get_inner() { return &inner_instance; }
};
You are right, it is best if the types used in the public API are not private. They may be forward declared only, though (if you only use pointers or references on the API).