I'm trying to redefine two member functions from their parent's definition.I don't know if I have it right or not, but something in my code has errors attached and I can't find out what.
some of the header:
class Account
{
public:
Account(double);
void creditBalance(double);
void debitBalance(double);
double getBalance() const;
protected:
double balance;
};
class CheckingAccount : public Account
{
public:
CheckingAccount(double, double);
void feeCreditBalance(double);
void feeDebitBalance(double);
private:
double fee = 10;
};
relevant cpp file part:
void Account::creditBalance(double plus)
{
if(plus > 0)
balance += plus;
else
cout << "Cannot credit negative.";
}
void Account::debitBalance(double minus)
{
if(minus <= balance)
balance -= minus;
else
cout << "Debit amount exceeded account balance.";
}
void CheckingAccount::feeCreditBalance(double plus)
{
if(plus > 0){
balance += plus;
balance -= fee;
}
else
cout << "Cannot credit negative.";
}
void CheckingAccount::feeDebitBalance(double minus)
{
if(minus <= balance){
balance -= minus;
balance -= fee;
}
else
cout << "Debit amount exceeded account balance.";
}
UPDATE:
I added this:
class Account
{
public:
Account(double);
virtual void creditBalance(double);
virtual void debitBalance(double);
double getBalance() const;
protected:
double balance;
};
Now I get error: virtual outside class declaration
I could use an example of how to properly initialize fee correctly.
EDIT 2:
I have tried changing the constructor line to this:
CheckingAccount::CheckingAccount(double initBal, double phi) : Account(initBal), fee(phi)
{
if(initBal < 0)
initBal = 0;
balance = initBal;
cerr << "Initial balance was invalid.";
if(phi < 0)
phi = 0;
fee = phi;
}
not working, I'm going to work around with changing syntax on the fee(phi) part. I don't know if anyone will respond to this.
You can not initialise member variables in place(double fee = 10) like that. You have to initialise then in the initiasation list in the derived class constructor. Also note that if you are using inheritance you should make base class destructor virtual.
If the intention is that for instances of CheckingAccount accounts the versions which use a fee is called, then you want to use virtual methods.
A virtual method is a method decalared (at least in the base class) as "virtual", and has the same name and signiture in any derived classes. When a virtual method is called, it will call the "most derived" version for the instance.
To do this just declare "void creditBalance(double);" and "void debitBalance(double);" virtual (ie "virtual void creditBalance(double);" and "virtual void debitBalance(double);". Then in CheckingAccount rename "feeCreditBalance" and "feeDebitBalance" to "creditBalance" and "debitBalance".
EDIT: Simple example.
Header
class Base
{
public:
Base(int x);
//declare virtual so that derived classes may overide it
virtual void sayHello();
protected:
int x;
};
class Derived : public Base
{
public:
Derived(int x, int y);
//overide Base::sayHello(). the virtual keyword here is optional.
virtual void sayHello();
protected:
int y;
};
Cpp
Base::Base(int x)
:x(x)
{}
Derived::Devired(int x, int y)
:Base(x), y(y)
{}
void Base::sayHello()
{
std::cout << "Hello from Base!" << std::endl;
std::cout << "X = " << x << std::endl;
}
void Derived::sayHello()
{
std::cout << "Hello from Derived!" << std::endl;
std::cout << "X = " << x << " Y = " << y << std::endl;
}
int main()
{
Base a(5);
a.sayHello();//"Hello from Base!..."
Derived b(10, -20);
b.sayHello();//"Hello from Derived!..."
Base *c = &b;//take pointer to b, reference would also do
c->sayHello();//"Hello from Derived!..." because its a Derived instance, eventhough its a Base variable.
}
You can then derive from Derive again (class DerivedAgain : public Derived) and also overload the functions again.
You can also derive multiple subclasses from Base, which can each have their own overrides for the virtual methods, just like I did for the Derived class.
EDIT2: Added variables to example and how to use initialiser list to initialise the base class and member variables.
When you want to override a method in the parent class, you should give the method the same name. Don't call it feeCreditBalance if you want it to override creditBalance. Also, you need to use the "virtual" keyword in the definition of the parent class's method if you want a call to creditBalance to always use the one from the child class.
You need to learn overriding the member function ( using virtual keyword) . IF you want to change the base class member function implementation then you need to override those methods and provide different implementation in derived classes.
EDIT:
double fee = 10;
This may be the error which you are talking. Use member initializer list to initialize fee. You cannot initialize fee as in-class constant.
I think fee should be static const if it remains constant and does not vary for each object.
Declare in the class like this:
static const double fee;
Define outside class like this:
const double ClassName::fee = 10;
And if you want your implementation should not allow -Ve balance than something like this and also you should make use of virtual functions in inheritance which is better approach:
void CheckingAccount::feeCreditBalance(double plus)
{
if(plus - fee > 0)
balance += (plus - fee);
else
cout << "Cannot credit negative.";
}
Related
So I have a parent class Transport and a child class Horse.
The parent class has a virtual function go() which the child uses to let the child object know how far to travel.
The parent class also has a method called get_dist_travelled() which returns the total distance travelled, but when called for the child object I noticed that the value hasen't been changed and it just returns 0.
Not sure if I am returning the right variable/not sure how to return the value I want/not sure even if I can do that (Without changing the fucntion's parameter)
Transport.h
class Transport{
private:
int kms;
int kmsAll;
public:
Transport();
int get_dist_travelled();
void virtual go();
};
Transport.cpp
Transport::Transport(){
}
int Transport::get_dist_travelled(){
return kmsAll;
}
void Transport::go(){
kmsAll=kmsAll+kms;
}
Horse.h
class Horse: public Transport{
private:
int kms;
int kmsAll;
public:
Horse();
void go(int kms);
};
Horse.cpp
Horse::Horse():Transport(){
kmsAll=0;
}
void Horse::go(int kms){
kmsAll=kmsAll+kms;
cout<<"The object has Traveled "<<kms<< " kms"<<endl;
}
Your horse has two sets of members. Those inherited from Transport named kms and kmsAll and those defined in its class definition called kms and kmsAll.
The members of Horse are shadowing those inherited from Transport. Hence in methods of Transport you are working on members of Transport and in methods of Horse you are working on members of Horse.
Instead of repeating the members from Transport in Horse the base class should grant access to them when the derived class needs access. Either provide public / protected getters or make the member itself protected (public not remcommended).
For example (the virtual method is fine, so I skip it for the example):
class transport {
protected:
int total_kms;
};
class horse : public transport {
void run(int km) { total_kms += km; }
}; // ^^ this is transport::total_kms
And here is an example that demonstrates what happens in your code:
#include <iostream>
struct transport {
int a = 1;
int b = 2;
};
struct horse : public transport {
int a = 42;
int b = 100;
void set() {
transport::a += 1;
transport::b += 1;
a -= 1;
b -= 1;
}
};
int main() {
horse h;
std::cout << h.a << "\n";
std::cout << h.b << "\n";
std::cout << h.transport::a << "\n";
std::cout << h.transport::b << "\n";
h.set();
std::cout << h.a << "\n";
std::cout << h.b << "\n";
std::cout << h.transport::a << "\n";
std::cout << h.transport::b << "\n";
}
Output:
42
100
1
2
41
99
2
3
Usually you want to avoid shadowing (two variables with same name in scope -> only one of them is directly accessible). When you have class members shadowing inherited members you can still access them by using their full name (eg h.transport::a accesses transport::a in h, actually not the "full name").
Imagine if I have class hierachy like this (Inheritance Hierarchy A):
Vehicle
MotorVehicle
Automobile
Motorcycle
WaterCraft
Sailboat
Canoe
If the Vehicle class contains functions named get_retail_price() and get_description(), and the get_description() function is overridden by every subclass in the hierarchy, without a virtual function in the base class, which get_description() function is executed by the following code?
void display_vehicle(const Vehicle& v)
{
std::cout << "Description: " << v.get_description() << ā\nā
<< "Retail price: " << v.get_retail_price() << "\n\n";
}
int main()
{
Motorcycle motorcycle("Harley-Davidson FXDR 114", 21349.0);
display_vehicle(motorcycle);
return 0;
}
I think it is the one in the Vehicle class because every subclass is redefining the get_descritption() function. But it the Vehicle class that calls it. Am I right to assume this?
And last question, what would happen if display_vehicle(const Vechicle& v) had a return type of any class? Something like Automobile display_vehicle(const Vehicle& v). Will it still call get_description() in the Vehicle class?
For member functions that are not virtual, it's the function of the known type that is invoked.
Here, the only known type is Vehicle:
void display_vehicle(const Vehicle& v)
{
std::cout << "Description: " << v.get_description() << ā\nā
<< "Retail price: " << v.get_retail_price() << "\n\n";
}
Note by the way that in such a case, you don't override the funcions. But you define a new function which hides the function of the base class.
If the function would be virtual, it would be the function of the object's real type that would be called.
Here a small snippet to show the different cases:
class Vehicle {
public:
virtual void show() { cout<<"I'm a vehicle"<<endl; } // virtual
void print() { cout <<"I'm a vehicle"<<endl; } // not virtual
void invokeshow() { show(); } // not virtual but invoking virtual
void invokespecificshow() { Vehicle::show(); } // not virtual invoking specific
~Vehicle() {} //at least one virtual ? then virtual destructor
};
class Motorcycle: public Vehicle {
public:
void show() override { cout<<"I'm a motorcycle"<<endl; }
void print() { cout <<"I'm a motorcycle"<<endl; }
};
void test(Vehicle &v) {
v.show();
v.print();
v.invokeshow();
v.invokespecificshow();
}
Online demo
I'm trying to create an array of pointers using polymorphism. I will have the array of the superclass point to multiple subclasses. Is there anyway of doing this and still using a method from the subclass? Here's a sample code:
#include <iostream>
class Test1
{
public:
Test1()
: x(1)
{}
int get_x()
{
return x;
}
private:
int x;
};
class Test2 : public Test1
{
public:
Test2()
: y(2)
{}
void print()
{
std::cout << get_x() << ' ' << y << std::endl;
}
private:
int y;
};
class Test3 : public Test1
{
public:
Test3()
: y(3)
{}
void print()
{
std::cout << get_x() << ' ' << y << std::endl;
}
private:
int y;
};
int main()
{
Test1** test = new Test1*[2];
for (int i = 0; i < 2; i++)
{
if (i % 2 == 0)
{
test[i] = NULL;
test[i] = new Test2;
}
else
{
test[i] = NULL;
test[i] = new Test3;
}
}
test[0]->print(); // ERROR. Is this even possible?
test[1]->print(); // ERROR. Is this even possible?
return 0;
}
Thank you I've only been coding for about 8 months.
test[0]->print(); // ERROR. Is this even possible?
In general, yes. However, not with your code.
If Test1 is going to be your base class and you're going to use new then it must have a virtual destructor (e.g., virtual ~Test1() {})
This is necessary for delete to work correctly when deleting a derived type via a pointer to the base class
Any function you want to call using a pointer to the base class must exist on the base class (i.e., you need a print function in Test1)
If you want the derived classes to have their own implementation of print then it must be declared virtual in the base class (e.g., virtual void print();)
If it dosn't make sense for Test1 to have an implementation of the print function then it can declare it pure virtual and not provide an implementation (e.g., virtual void print() = 0;) thus making it an abstract class
It would be if Test1 had such a member function named print. Your code doesn't compile as-is because Test::print doesn't exist. So at the very least, you will have to define that member function. For it to be truly polymorphic, as the intent of the question suggests, you should make Test::print a virtual member function so that Test2's and Test3's implementations of that function would get called instead:
class Test1 {
...
virtual void print() {
std::cout << "Test1" << std::endl;
}
...
};
For more information, see this tutorial on virtual functions.
In c++ pass to a function/method a derived class, in the place of a base class and still have information about the derived class?.
Ex: Say that I have a base class: "geometry" and some other class: "shape" form where I derive "rectangle" and "circle".
double area::geometry( shape& object, int i )
{
if i = 1:
rectangle thisObject = object;
double side1 = thisObject.getheight();
double side2 = thisObject.getwidth();
if i = 2:
circle thisObject = object;
double side1 = thisObject.radius * thisObject.radius;
double side2 = 3.14;
return side1 * side2;
}
The problem is that you have to suppose that the "return side1 * side2", is a very complicated code that I don't want to repeat. So I prefer to set up the problem depending on the type of input to the function, than to overload it.
The idea is very similar to this one: Is it possible to pass derived classes by reference to a function taking base class as a parameter.
Thanks!
Edit: Tried to make the code clearer.
The usual approach would be to use polymorphism:
void func(const base& ob)
{
ob.doSomethingPolymorphic();
}
where doSomethingPolymorphic() is a virtual member function of base.
If func needs to know what type ob is when you pass it in, "you are doing it wrong". The WHOLE POINT of polymorphism is that all objects appear to be the same from an outside observer, but internally do different things. The typical example is animals:
#include <iostream>
using namespace std;
class Animal
{
public:
virtual void Say() = 0;
};
class Dog : public Animal
{
public:
void Say() { cout << "Woof Woof" << endl; }
};
class Pig : public Animal
{
public:
void Say() { cout << "All animals are equal, but pigs are "
"more equal than other animals" << endl; }
};
class Cat : public Animal
{
public:
void Say() { cout << "Meow, Meow" << endl; };
};
void AnimalTalk(Animal *a[], int size)
{
for(int i = 0; i < size; i++)
{
a[i]->Say();
}
}
int main()
{
Cat c;
Pig p;
Dog d;
Animal* list[3] = { &p, &c, &d };
AnimalTalk(list, 3);
}
I have a parent class which as a member contains an array of pointers to objects of the same type as itself. I have another class that derives from the parent class. I want that the derived class uses an array of pointers to objects of its own (not the parent class). The deriving class calls methods on those objects that are stored in the array of pointers; it calls both methods which are defined and implemented in the derived class as well as in the base class. The code below obviously doesn't compile as parent contains no member z (in derived::doX()). I could dyanamic_cast(p[i]).z before accessing z, but I would have to do that on EVERY method in b at runtime.
If I hide "p" in the derived class (by casting the p's during object construction), I essentially get two arrays of pointers p, however, I want all methods operate on the same objects (residing in p). I tried templates but ran into a recursive issue. Any idea how to solve this?
#include <iostream>
#include <stdlib.h>
using namespace std;
class parent{
protected:
parent** p;
int num;
int x;
public:
parent(int _num, parent** _ps);
virtual void doX();
virtual void print();
};
class derived : public parent {
protected:
//derived** p;
int z;
public:
derived(int _num, parent** _ps) : parent(_num, _ps){};
virtual void doX();
virtual void print();
};
void parent::doX(){
for(int i=0;i<num;i++){
p[i]->x = 1;
}
}
void parent::print(){ cout << "x " << x << endl;
}
parent::parent(int _num, parent** _ds){
num=_num;
p = _ds;
}
void derived::doX(){
for(int i=0;i<num;i++){
p[i]->z = 2;
}
parent::doX();
}
void derived::print(){
cout << "x " << x << endl;
cout << "z " << z << endl;
}
int main(){
const int NUM = 2;
parent** ps = (parent**)malloc(sizeof(parent)*NUM);
for(int i=0; i< NUM; i++){
ps[i] = new derived(NUM, ps);
}
ps[0]->doX();
ps[0]->print();
ps[0]->print();
}
You are on the right track! You should use the "p" defined in the parent class. In the derived class setter methods you enforce that the derived type must be used (as the parameter type). For instance your constructor for defined will be:
derived(int _num, derived** _ps) : parent(_num, _ps){};
Then, when you're using p in the derived methods, you know that p is really a derived type, and you can safely cast it.