Having been taught Java, I am confused by how Object Orientation is implemented in C++.
Having this class:
class Car {
int weight;
public:
Car(int input) {
weight = input;
}
void sayVroem() {
std::cout << "Vroem...";
}
};
In Java I would be able to declare this an abstract class by declaring it as public abstract class Car. This would result in that the class cannot be instantiated. Is something similar possible in c++?
You need to declare at least one method pure virtual, like:
class Car {
int weight;
public:
Car(int input) {
weight = input;
}
void sayVroem() {
std::cout << "Vroem...";
}
virtual void ImAPureVirtualMethod() = 0;
};
If you have no virtual methods
class Car {
int weight;
public:
void sayVroem() {
std::cout << "Vroem...";
}
protected:
Car () = default;
};
Or by making the destructor pure virtual like
class Car {
int weight;
public:
Car(int input) {
weight = input;
}
void sayVroem() {
std::cout << "Vroem...";
}
virtual ~Car() = 0;
};
One thing to be aware of when using virtual descructors is that when a derived class is destroyed it will call the base class descructor so you will need to provide an implementation, for example:
inline Car::~Car() { }
There are plenty of stuff out there describing this:
https://en.cppreference.com/w/cpp/language/abstract_class
https://www.geeksforgeeks.org/pure-virtual-functions-and-abstract-classes/
The easiest way to do this explicitly is to declare all constructors as protected => Then you won't be able to instantiate the class even without pure virtual members.
In your case:
class Car {
int weight;
protected: // only derived classes can access those functions
Car(int input) {
weight = input;
}
// if you just have the default c-tor you can move it to protected like this:
Car() = default;
public:
void sayVroem() {
std::cout << "Vroem...";
}
// feel free to add virtual methods later on if required
};
Have you tried searching online ?
I'm not using C++ but the research seems pretty easy and with plenty of answers.
IBM Explanation of C++ abstract classes
Wikibooks - C++ Programming/Classes/Abstract Classes
Related
I have an abstract class Job and other classes that implement it like:
Waiter and Builder, all of them implement my function in the same way.
For example:
Waiter::changeScore()
{
score += top_score;
}
How may I prevent this kind of code duplication?
Constraints:
I want to keep Job abstract.
Each Waiter or Builder has its own top_score value (It differs between classes and objects of the same class).
Not all member functions of an abstract class need to be pure virtual (as long as at least one is). Your changeScore member is an ideal candidate as a 'real' base class function. Further, not only does it not need to be pure virtual, it doesn't even need to be virtual at all (unless you want your polymorphism to change what a pointer to a derived class will see, for that function).
As each class (or object) will have its own value of top_score (as you have stated), then that (data) member can also be part of the 'abstract' base class.
You can even add a single 'dummy' pure virtual function in your base class (which is never intended to be used, even by a derived class), just to make sure that instances aren't accidentally created. For example, your Job class could have a member:
virtual int Dummy() = 0;
Then, any derived class must have an override for that (however trivial), or the compiler won't allow you to declare an instance of that class. So, your Waiter class would need something like:
int Dummy override { return 1; }
The following code sample may help/demonstrate the idea:
#include <iostream>
#include <memory> // So we can use smart pointers
class Job {
public:
int score{ 0 }, top_score{ 0 };
public:
Job() { }
virtual ~Job() = default;
virtual void Dummy() = 0; // This is sufficient to make the class abstract!
void changeScore() {
score += top_score;
}
virtual void showName() {
std::cout << "Generic Job" << std::endl;
}
};
class Waiter : public Job {
public:
Waiter(int top = 5) { top_score = top; }
~Waiter() override = default;
void Dummy() override { } // We need this in order to use Waiter
void showName() override {
std::cout << "Waiter" << std::endl;
}
};
class Builder : public Job {
public:
Builder(int top = 10) { top_score = top; }
~Builder() override = default;
void Dummy() override { } // We need this in order to use Builder
void showName() override {
std::cout << "Builder" << std::endl;
}
};
int main()
{
Waiter w{ 6 }; // OK - uses explicit value for 'top' parameter
Builder b; // OK - uses default value for 'top' parameter
// Job j; // ERROR - Cannot instantiate abstract class
w.changeScore();
b.changeScore();
std::cout << w.score << std::endl;
std::cout << b.score << std::endl;
// Also, using pointers...
// Job* pj = new Job; // ERROR - Cannot instantiate abstract class
Job* pw = new Waiter; // OK - Now we can make use of polymorphism...
Job* pb = new Builder; // ...with either of these 2 "Job" pointers!
pw->showName();
pb->showName();
delete pw;
delete pb;
// Polymorphism also works with smart pointers (which you SHOULD be using) ...
// std::unique_ptr<Job> upj = std::make_unique<Job>(); // ERROR - Allocating an object of abstract class
std::unique_ptr<Job> upw = std::make_unique<Waiter>(15);
upw->changeScore();
std::cout << upw->score << ": ";
upw->showName();
std::unique_ptr<Job> upb = std::make_unique<Builder>(42);
upb->changeScore();
std::cout << upb->score << ": ";
upb->showName();
return 0;
}
You can define the method in the base class:
Live demo
class Job {
private:
int score;
int top_score;
protected:
//protected constructor to be inherited by derived classes
Job(int top_score) : top_score(top_score) {}
//one pure virtual method is enough to make the class abstract
virtual void some_method() = 0;
public:
void changeScore() { //single method implementation
score += top_score;
}
//to use polymorphism you must use a virtual destructor, unless you use shared_ptr
virtual ~Job(){}
};
class Waiter : public Job {
public:
Waiter(int top_score) : Job(top_score) {}
// pure virtual methods must be overridden in all derived classes
void some_method() override{}
};
class Builder : public Job {
public:
Builder(int top_score) : Job(top_score) {}
void some_method() override{}
};
changeScore() will be implemented in the abstract class and will be usable by all derived classes.
Waiter w(10); //top_score 10
Buider b(20); // top_score 20
b.changeScore();
w.changeScore();
You can make the changeScore method a pure virtual method AND provide an implementation. This would look like this:
class Job {
int score{0};
int top_score{0};
public:
virtual void changeScore() = 0;
};
void Job::changeScore()
{
score += top_score;
}
Then you can call the changeScore method of the Job base class in the child classes like this:
class Waiter : public Job {
public:
virutal void changeScore() override {
Job::changeScore();
}
};
This way if you want to change changeScore, you do not need to change all the implementations in the child classes, but you can just change the implementation in the Job class.
This way you do not need any dummy methods and the Job class remains abstract, while the override in the child classes is trivial and you have a single implementation if you ever want to change it.
EDIT:
If you are wondering where this override keyword comes from, it is introduced in C++11. Since I do not know which C++ version you are using I just wanted to point that out.
You can read about the override specifier here
EDIT II:
Regarding that ever child class has its own top_score, you should set this via the constructor of those child classes.
Like this:
class Job {
protected:
int top_score{0};
Job(top) : top_score(top) {}
...
};
class Waiter : public Job {
public:
Waiter(int top): Job(top) {}
...
};
This way each child class has its own version of top_score
EDIT III:
Putting it all together the classes would look something like this:
class Job {
protected:
int score{0};
int top_score{0};
Job(top) : top_score(top) {}
public:
virtual void changeScore() = 0;
};
void Job::changeScore()
{
score += top_score;
}
class Waiter : public Job {
public:
Waiter(int top): Job(top) {}
virutal void changeScore() override {
Job::changeScore();
}
};
#include <iostream>
#include <string>
using namespace std;
class Employee
{
public :
virtual int calculateSalary()= 0;
virtual string getName()=0;
virtual string getEngineer()=0; //error
virtual string getManager()=0; /error
virtual string getDirector()=0; /error
};
class Engineer: public Employee
{
protected:
string name;
int salary;
public:
Engineer(string n,int s):name(n),salary(s){ cout<<endl<<"Engineer Created"; }
~Engineer(){cout<<endl<<"engineer destroyed";}
int calculateSalary()
{
return salary * 2;
}
string getName()
{
return name;
}
string getEngineer()
{
return "Engineer";
}
};
class Manager:public Engineer
{
public:
Manager(string n,int s): Engineer(n,s) { cout<<endl<<"Manager Created"; }
~Manager(){cout<<endl<<"MANAGER destroyed";}
int calculateSalary()
{
return salary * 3;
}
string getName()
{
return name;
}
string getManager()
{
return "manager";
}
};
class Director:public Manager
{
public:
Director(string n,int s): Manager(n,s) { cout<<endl<<"Director Created"; }
~Director(){cout<<endl<<"Director destroyed";}
int calculateSalary()
{
return salary * 4;
}
string getName()
{
return name;
}
string getDirector()
{
return "director";
}
};
int main()
{
Engineer e1("rohit",20000),e2("soham",21000);
Manager m1("shyam",23000),m2("ram",23500);
Director d1("rahul",25000);
Employee *staff[] = {&e1,&e2,&m1,&m2,&d1};
for(int i=0;i<5;i++)
{
cout<<endl<<"Name : "<<staff[i]->getName() << "\t" << "Salary : " << staff[i]->calculateSalary();
}
cout<<endl<<staff[0]->getEngineer(); //error
cout<<endl<<staff[1]->getEngineer(); //error
cout<<endl<<staff[2]->getManager(); //error
cout<<endl<<staff[3]->getManager(); //error
cout<<endl<<staff[4]->getDirector(); //error
return 0;
}
/The lines with error are showing errors if i compile this code.
i want to know if it is possible to access the getEngineer(),getManager(),getDirector() via the staff pointer.
If yes, then how?
If not, then why?
and is there any alternative to access those functions keeping the data type of staff as it is(i.e Employee) ?/
All derived class from Employee must to implement all pure virtual methods, otherwise they cannot be instanced.
Why does this happen?
A derivative class inherits all methods (and member variables) from the base class.
In you case, base class has some pure virtual methods, and so the sub-classes (Engineer, Manager and Director) as well. A no-abstract class cannot have a pure virtual method, so in order to instantiate those classes, each of them should implement getEngineer() getManager() getDirector() methods.
What is the solution?
The problem in your case is a bad design decision.
The base class should represent a uniform interface for all derivative classes.
That's why, the base class Employee should not have method like getEngineer() which is a more specific information.
IMO, a better design decision (just looking at your code) could be:
class Employee {
public :
virtual int calculateSalary() = 0;
virtual string getName() = 0;
virtual string getTypeWork() = 0;
};
In that way (exploiting polymorphism property) each derivative class can correctly return a string representing its role job.
it is possible to access the getEngineer(),getManager(),getDirector() via the staff pointer. If yes, then how?
Yes, you can. However, as #Biagio Festa said you can't have pure virtual functions in your base class Employee without implementing them in your derived ones. So one solution could be having default implementations for those functions in your base class
class Employee
{
public :
virtual int calculateSalary()= 0;
virtual string getName()=0;
virtual string getEngineer() { return std::string(); }
virtual string getManager() { return std::string(); }
virtual string getDirector() { return std::string(); }
};
Then, you can override those functions in your derived classes only when needed like you did in your example.
Trying to get my head round using polymorphism in C++. Below are two base abstract classes, Duck and FlyingBehavior, and a series of inherited classes (this is based on the first chapter from Head First Design Patterns).
// Define an abstract fly behaviour class
class FlyBehavior {
public:
virtual void fly() { cout << "No Flying Set!" << endl; }
};
class FlySwoop : public FlyBehavior {
public:
void fly() { cout << "Swoop Flying!" << endl; }
};
class CantFly : public FlyBehavior {
public:
void fly() { cout << "Can't Fly!" << endl; }
};
// Define an abstract Duck class
class Duck {
CantFly nf;
FlyBehavior *flyBehavior;
public:
Duck() { flyBehavior = &nf; }
void goFly() { flyBehavior->fly(); }
void setFlyBehavior(FlyBehavior *fb) { flyBehavior = fb; }
};
// Define a new Mallard Duck class
class MallardDuck : public Duck {
FlySwoop fb;
public:
MallardDuck(){ setFlyBehavior(&fb); }
};
// Define a new Rubber Duck class
class RubberDuck : public Duck {
CantFly fb;
public:
RubberDuck(){ setFlyBehavior(&fb); }
};
// Define a new Toilet Duck Class
class ToiletDuck : public Duck {};
int main(void) {
Duck *p;
MallardDuck mallardDuck;
RubberDuck rubberDuck;
ToiletDuck toiletDuck;
p = &mallardDuck;
p->goFly();
p = &rubberDuck;
p->goFly();
p = &toiletDuck;
p->goFly();
}
Using the above code I get the following output
Swoop Flying!
Can't Fly!
Can't Fly!
when I was expecting
Swoop Flying!
Can't Fly!
No Flying Set!
Am I approaching this example the right way (use to doing it in Java)? Can't help but feel that I'm missing something fundamental. I'm trying to understand how you pull out a behaviour from a class, put it into another class, and then use polymorphism to delegate to the right behavior. Is there a better way to approach the above?
Hmmm, perhaps this where you use multiple inheritance instead?
If you change
class Duck {
CantFly nf;
FlyBehavior *flyBehavior;
public:
Duck() { flyBehavior = &nf; }
void goFly() { flyBehavior->fly(); }
void setFlyBehavior(FlyBehavior *fb) { flyBehavior = fb; }
};
to
class Duck {
FlyBehavior nf;
FlyBehavior *flyBehavior;
public:
Duck() { flyBehavior = &nf; }
void goFly() { flyBehavior->fly(); }
void setFlyBehavior(FlyBehavior *fb) { flyBehavior = fb; }
};
your code will produce desired output.
In the current version of the code ToiletDuck compiler-generated default constructor calls a default constructor of the Duck class which sets nf to point to an instance of theCantFly class. Of course, it prints Can't fly.
First, your code has no abstract base classes. An abstract base class is one that has pure virtual member functions (such as virtual fly() const=0). FlyBehavior is a polymorphic class, but not abstract, since its virtual function is not pure virtual. Duck is not even a polymorphic class (has no virtual member methods).
Second, any polymorphic classes should have a virtual destructor, so that any object of derived type can be deleted from a pointer to the polymorphic base.
Next, the derived ducks have more data members than actually used. MallardDuck, for example, has a CantFly, a FlySwoop and a FlyBehaviour*. This can be avoided by allocating the actual FlyBehaviour on the heap and managing it through a smart pointer. (This may not be an issue with this simple example, but as soon as those objects get large it will become a problem.)
Finally, the member function setFlyBehavior() is exposed to the public, allowing the user to change the FlyBehavior -- do you really want that?
A possible design is as follows
struct FlyBehavior // polymorphic class
{
virtual void fly() const { cout << "No Flying Set!" << endl; }
virtual~FlyBehavior() {}
};
struct FlySwoop : FlyBehavior
{
void fly() const { cout << "Swoop Flying!" << endl; }
};
struct CantFly : FlyBehavior
{
void fly() const { cout << "Can't Fly!" << endl; }
};
class Duck // non-polymorphic, but using polymorphism through member
{
std::unique_ptr<FlyBehavior> flyBehavior; // calls FlyBehavior::~FlyBehavior at destruction
protected:
explicit Duck(FlyBehavior*f) : flyBehavior(f) { assert(f); }
public:
Duck() : flyBehavior(new FlyBehavior) {} // note: not CantFly as in your code
Duck(Duck&&) = default; // allow move (but no copy)
Duck&operator=(Duck&&) = default;
void goFly() const { flyBehavior->fly(); }
};
struct MallardDuck : Duck
{
MallardDuck() : Duck(new FlySwoop) {}
};
struct RubberDuck : Duck
{
RubberDuck() : Duck(new CantFly) {}
};
Often it is preferrable for FlyBehavior to be abstract. In this case, Duck can be implemented with only a protected constructor (apart from move & copy):
struct FlyBehavior // polymorphic class
{
virtual void fly() const=0 ; // pure virtual
virtual~FlyBehavior() {}
};
class Duck // non-polymorphic, but using polymorphism through member
{
std::unique_ptr<FlyBehavior> flyBehavior; // calls FlyBehavior::~FlyBehavior at destruction
protected:
explicit Duck(FlyBehavior*f) : flyBehavior(f) { assert(f); }
public:
Duck() = delete; // no default constructor
Duck(Duck&&) = default; // allow move (but no copy)
Duck&operator=(Duck&&) = default;
void goFly() const { flyBehavior->fly(); }
};
and the remaining code as above. The difference is that you cannot create a Duck object, but only one of the derived Duck types. Which of these two designs is most suitable depends on the application.
I am trying to define an interface called "Algorithm" which has a pure virtual method insertData(InputData* input).
The implementation of the interface is called "Algorithm1" and i want to implement method "insertData" using as a parameter "SpecificData" which is a child of "InputData" class.
Is it possible without type casting?
Obviously with this code i get an error from the compiler that the virtual function "insertData" is pure within "Algorithm1".
class Algorithm{
public:
virtual ~Algorithm();
virtual void insertData(InputData* input) = 0;
};
class Algorithm1 : public Algorithm{
public:
Algorithm1();
virtual ~Algorithm1();
void insertData(SpecificData* input){
input.getID();
input.getAdditionalNumbers;
/*Process input information etc.*/ };
};
class InputData{
public:
void setID(int id){ this->id = id; }
int getID(){ return id;};
private:
int id;
};
class SpecifiData : public InputData{
public:
list<int> getAdditionalNumbers(){/*Return various Numbers*/};
private:
list<int> extraInfo;
};
void main(){
SpecificData* data = new SpecificData();
Algorithm* alg = new Algorithm1();
alg->insertData(data);
}
For insertData to be the same function (rather than "hiding" the original insertData, you need the two functions to have the same arguments (and same return type).
The whole idea of interfaces using virtual functions is that "they appear the same from the outside". You should be able to build a list of objects, and perform the same operation with the same input data for all of the objects in the list.
If you are breaking that principle, you are "doing it wrong".
No, it wouldn't make sense.
Think about the following scenario - you have a container (vector/set w/e) of Algorithm* type objects and a function that takes this container and a InputData* in as an input and then iterate over them and call insertData(in) on each of the objects in the container, this of course should work properly, but if one of the objects in your container is of type Algorithm1 what will happen then?
I think, this is a typical example of "Factory Method" in design pattern term.
class Algorithm
{
public:
virtual ~Algorithm();
virtual void insertData(InputData* input) = 0;
};
class InputData
{
public:
void setID(int id){ this->id = id; }
int getID(){ return id;};
virtual list<int> getAdditionalNumbers() = 0;
private:
int id;
};
class Algorithm1 : public Algorithm
{
public:
Algorithm1();
virtual ~Algorithm1();
void insertData(InputData* input){
input.getID();
input.getAdditionalNumbers;
/*Process input information etc.*/ };
};
class SpecifiData : public InputData
{
public:
// implementation
virtual list<int> getAdditionalNumbers(){/*Return various Numbers*/};
private:
list<int> extraInfo;
};
void main()
{
InputData* data = new SpecificData();
Algorithm* alg = new Algorithm1();
alg->insertData(data);
}
I would to block child classes from overriding a base method and have the child classes override a new method in a parental class. In other words, a child class of the base class blocks the base class methods and delegates to a new method that further child classes must override. I still want the base class method to be available.
Here is an example:
#include <iostream>
#include <string>
struct Base
{
virtual const std::string& class_name(void) = 0;
};
struct Level1
: public Base
{
private: // Prevent child classes from overriding
// the Base::class_name method
const std::string& class_name(void)
{
static std::string name;
name = "class" + class_name_from_level_1();
return name;
}
protected:
// This is the "new" or redirected class that child classes
// must override.
virtual const std::string& class_name_from_level_1(void) = 0;
};
struct Level2
: public Level1
{
static std::string name;
const std::string& class_name_from_level_1(void)
{
if (name.length() == 0)
{
name = "Level2";
}
return name;
}
};
int main(void)
{
Level2 lev2;
std::cout << lev2.class_name() << "\n";
return 0;
}
I am getting the following errors from g++:
$ g++ hiding_virt_methods.cpp -o hiding_virt_methods.exe
hiding_virt_methods.cpp: In function `int main()':
hiding_virt_methods.cpp:15: error: `virtual const std::string& Level1::class_name()' is private
hiding_virt_methods.cpp:43: error: within this context
In the above example, I want the following chain of execution for Level2:
Base::class_name() --> Level1::class_name_from_level_1() --> Level2::class_name_from_level_1()
Also, I only want to block inheritance of specific methods in the Base class. Protected and Private Inheritance affect all the public methods.
So how do I stop the chain of inheritance of specific Base methods at different levels in the inheritance tree?
Edit: Real world example.
I have an interface class Record. Class Record_With_Id inherits from class Record and adds an ID field. The class Record contains an accept_visitor method. Class Record_With_Id overrides accept_visitor to apply to the ID field, then calls a virtual method, record_with_id_accept_visitor, which descendants must implement.
For your immediate problem, you can rename your class_name() functions to class_name_impl() or similar, then in the base class have a class_name() function that calls the implementation one. That way, only the base class version will match when calling class_name() on a derived object.
More generally, you can frustrate attempts to call the base class methods by having same-named functions in the derived classes - as you've done, but anyone can cast to a Base& and call whatever they like. You can't stop virtual methods being overridable in derived classes... you can only frustrate their use.
It's worth remembering that a publicly derived class IS an instance of the base class, and SHOULD provide the base class's interface.
EDIT: re yout "real world example" edit, can you explain the problem with a normal implementation ala...
#include <iostream>
struct Visitor
{
virtual void operator()(int&) const = 0;
};
struct X
{
virtual void visit(Visitor& v) { v(a); v(b); }
int a;
int b;
};
struct X_with_C : X
{
int c;
virtual void visit(Visitor& v) { X::visit(v); v(c); }
};
struct My_Visitor : Visitor
{
void operator()(int& n) const { std::cout << ++n << '\n'; }
};
int main()
{
X x;
x.a = 10;
x.b = 20;
My_Visitor visitor;
x.visit(visitor);
X_with_C xc;
xc.a = -10;
xc.b = -20;
xc.c = -30;
xc.visit(visitor);
X& rx = xc;
rx.visit(visitor);
}
Output:
11
21
-9
-19
-29
-8
-18
-28
hasn't C++11 added final and override?
http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final
Four years later, let me add that C++11 has introduced keyword final:
class Base final {
This can also be applied on the virtual methods:
class Base{
protected:
virtual void doWork() = 0;
public:
virtual void startWork() final { doWork(); }
};
class Derived: public Base{
protected:
virtual void doWork() override { /* some work */ }
public:
// error: overriding final function ‘virtual void Base::startWork()’
virtual void startWork() override { /* something else */ }
};
Visual Studio 2005 and above implement a keyword "sealed", which is a Microsoft extension to C++. You put it in the declaration of Level1::class_name(). I don't think there is a portable way.
It appears that you're trying to do something in a way that's hard.
Depending on what it is that you're trying to achieve, the following may be a solution.
#include <iostream>
#include <string>
struct Base
{
virtual std::string class_name() const = 0;
};
class Level1
: public Base
{
public:
std::string class_description() const
{
return "class " + class_name();
}
};
class Level2
: public Level1
{
public:
virtual std::string class_name() const
{
return "Level2";
}
};
int main()
{
Level2 lev2;
std::cout << lev2.class_description() << "\n";
}
In the above code I've assumed it's for debugging/tracing or something like that. For id purposes look into typeid (a built-in operator).
Cheers & hth.,