I'm making an inventory system, and am trying to use derivatives to create different items, so that I can have default elements in the parent and specialized ones in the children.
So what I've written below, at the moment it prints "I'm a parent" but I am trying to get it to print "I'm a kid", and in the lack of a child definition of stuffToSay print "I'm a parent" Thanks!
using namespace std;
class myParent {
public:
virtual void saySomething() {
cout << stuffToSay;
}
string stuffToSay = "I'm a parent";
private:
};
class myDerivitive : public myParent{
public:
myDerivitive() {};
string stuffToSay = "I'm a kid";
private:
};
int main() {
myParent* people[] = {
new myDerivitive()
};
cout << people[0]->stuffToSay;
system("pause");
}
Thats not how it works. The saySomething in parent doesn't know anything about the string in the derived class and member variables aren't virtual.
You can do it e.g. like this
#include <iostream>
#include <string>
struct myParent {
void saySomething() {
cout << getSomething();
}
virtual std::string getSomething(){ return "I'm a parent"; }
virtual ~myParent(){} // virtual destructor is needed
};
struct myDerived : myParent {
virtual std::string getSomething(){ return "I'm the derived"; }
};
int main() {
myParent* p = new myDerived();
p->saySomething();
delete p; // dont forget to delete !!
}
Something like this is normally done using the constructor of your class, the child class has all the variables of its parent class so to do what you are looking for it can be done like this:
using namespace std;
class myParent {
public:
myParent() {
stuffToSay = "I'm a parent"
}
virtual void saySomething() {
cout << stuffToSay;
}
string stuffToSay;
private:
};
class myDerivitive : public myParent{
public:
myDerivitive() {
stuffToSay = "I'm a kid";
};
private:
};
int main() {
myParent* people = new myDerivitive();
cout << people->stuffToSay();
delete people; // Simplified to a single pointer and remember to delete it
people = NULL;
system("pause");
}
Please take a look at this link for more information on classes:
http://www.cplusplus.com/doc/tutorial/classes/
This link will help with the understanding of inheritance, since your derivative class would have the "stuffToSay" variable since its parent had it:
http://www.cplusplus.com/doc/tutorial/inheritance/
There is no such thing as a virtual or overridden variable in C++; that sort of polymorphism only applies to methods. So you could do this:
struct parent {
virtual void saySomething() {
cout << "I'm a parent!\n";
}
};
struct child: parent {
void saySomething() override {
cout << "I'm a child!\n";
}
};
Or you could solve it with something more like your current structure by adding a layer of indirection:
struct parent {
void saySomething() {
cout << thingToSay() << '\n';
}
private:
virtual string thingToSay() { return "I'm a parent!"; }
};
class child: parent {
virtual string thingToSay() { return "I'm a child!"; }
};
Related
I have a component in a software that can be described by an interface / virtual class.
Which non-virtual subclass is needed is decided by a GUI selection at runtime.
Those subclasses have unique methods, for which is makes no sense to give them a shared interface (e.g. collection of different data types and hardware access).
A minimal code example looks like this:
#include <iostream>
#include <memory>
using namespace std;
// interface base class
class Base
{
public:
virtual void shared()=0;
};
// some subclasses with shared and unique methods
class A : public Base
{
public:
void shared()
{
cout << "do A stuff\n";
}
void methodUniqueToA()
{
cout << "stuff unique to A\n";
}
};
class B : public Base
{
public:
void shared()
{
cout << "do B stuff\n";
}
void methodUniqueToB()
{
cout << "stuff unique to B\n";
}
};
// main
int main()
{
// it is not known at compile time, which subtype will be needed. Therefore: pointer has base class type:
shared_ptr<Base> basePtr;
// choose which object subtype is needed by GUI - in this case e.g. now A is required. Could also have been B!
basePtr = make_shared<A>();
// do some stuff which needs interface functionality... so far so good
basePtr->shared();
// now I want to do methodUniqueToA() only if basePtr contains type A object
// this won't compile obviously:
basePtr->methodUniqueToA(); // COMPILE ERROR
// I could check the type using dynamic_pointer_cast, however this ist not very elegant!
if(dynamic_pointer_cast<A>(basePtr))
{
dynamic_pointer_cast<A>(basePtr)->methodUniqueToA();
}
else
if(dynamic_pointer_cast<B>(basePtr))
{
dynamic_pointer_cast<B>(basePtr)->methodUniqueToB();
}
else
{
// throw some exception
}
return 0;
}
Methods methodUniqueTo*() could have different argument lists and return data which is omitted here for clarity.
I suspect that this problem isn't a rare case. E.g. for accessing different hardware by the different subclasses while also needing the polymorphic functionality of their container.
How does one generally do this?
For the sake of completeness: the output (with compiler error fixed):
do A stuff
stuff unique to A
You can have an enum which will represent the derived class. For example this:
#include <iostream>
#include <memory>
using namespace std;
enum class DerivedType
{
NONE = 0,
AType,
BType
};
class Base
{
public:
Base()
{
mType = DerivedType::NONE;
}
virtual ~Base() = default; //You should have a virtual destructor :)
virtual void shared() = 0;
DerivedType GetType() const { return mType; };
protected:
DerivedType mType;
};
// some subclasses with shared and unique methods
class A : public Base
{
public:
A()
{
mType = DerivedType::AType;
}
void shared()
{
cout << "do A stuff\n";
}
void methodUniqueToA()
{
cout << "stuff unique to A\n";
}
};
class B : public Base
{
public:
B()
{
mType = DerivedType::BType;
}
void shared()
{
cout << "do B stuff\n";
}
void methodUniqueToB()
{
cout << "stuff unique to B\n";
}
};
// main
int main()
{
shared_ptr<Base> basePtr;
basePtr = make_shared<B>();
basePtr->shared();
// Here :)
if(basePtr->GetType() == DerivedType::AType)
static_cast<A*>(basePtr.get())->methodUniqueToA();
else if(basePtr->GetType() == DerivedType::BType)
static_cast<B*>(basePtr.get())->methodUniqueToB();
return 0;
}
You can store an enum and initialize it at the constructor. Then have a Getter for that, which will give you the Type. Then a simple static cast after getting the type would do your job!
The goal of using polymorphism for the client is to control different objects with a single way. In other words, the client do not have to pay any attention to the difference of each object. That way, checking the type of each object violates the basic goal.
To achieve the goal, you will have to :
write the concrete method(methodUniqueToX()).
write a wrapper of the concrete method.
name the wrapper method abstract.
make the method public and interface/abstract.
class Base
{
public:
virtual void shared()=0;
virtual void onEvent1()=0;
virtual void onEvent2()=0;
};
// some subclasses with shared and unique methods
class A : public Base
{
private:
void methodUniqueToA()
{
cout << "stuff unique to A\n";
}
public:
void shared()
{
cout << "do A stuff\n";
}
void onEvent1()
{
this.methodUniqueToA()
}
void onEvent2()
{
}
};
class B : public Base
{
private:
void methodUniqueToB()
{
cout << "stuff unique to B\n";
}
public:
void shared()
{
cout << "do B stuff\n";
}
void onEvent1()
{
}
void onEvent2()
{
methodUniqueToB()
}
};
I am trying to do something like this:
class Movement {
public:
virtual void move() = 0;
};
class Walk : public Movement {
public:
void move() { cout << "walking"; }
};
class Run : public Movement {
public:
void move() { cout << "run"; }
};
class Animal {
public:
virtual void print();
};
class Human : public Animal {
public:
void print() { cout << "Human"; }
};
class Lion : public Animal {
public:
void print() { cout << "Lion"; }
};
class Model {
Animal* animal;
Movement* movement;
public:
Model(Animal* animal = new Human(), Movement* movement = new Walk()) {
this->animal = animal;
this->movement = movement;
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first = Model(), second = Model(new Lion(), new Run());
first.print();
cout << endl;
second.print();
return 0;
}
How do we set the default value for abstract class pointers & how to pass them as a parameter like that from main?
I would also prefer to be able to pass arguments from main like this only in a single line without needing to initialize before.
can anyone please help me with how do we such things in C++?
I have tried and searched a lot but no luck.
I am looking for a workaround to do something like this, in which we use an abstract classes as a parameter of other classes.
I know objects cannot be assigned to a pointer, I just don't know what to do there to fulfill my requirement, an abstract class as a parameter with a default value.
This is my latest attempt with exact code, but unfortunately with new, does anyone know how to get rid of new and achieve the desired outcome?
Note:
My actual code is quite complex, basically using an abstract class for polymorphism and pass those abstract classes as parameters to another class with default parameters, if there is ANY other way to do something similar I would really appreciate the help.
This is really a design question. In Modelclass design, you either need to decide about the object ownership, or defer the decision to the calling code. In the latter case, you cannot have default arguments (unless you want to have global constants Human and Walk, but I would not recommend it).
One way to have the default arguments is to decide that Model has exclusive ownership of Animal and Movement, and store unique_ptrs to them. Something like this:
class Model {
unique_ptr<Animal> animal;
unique_ptr<Movement> movement;
public:
Model(unique_ptr<Animal> animal = make_unique<Human>(), unique_ptr<Movement> movement = make_unique<Walk>()){
this->animal = std::move(animal);
this->movement = std::move(movement);
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first/*no () here!*/, second(make_unique<Lion>(), make_unique<Run>());
first.print();
cout << endl;
second.print();
return 0;
}
I think I came up with the best solution for my situation.
#include <iostream>
#include <memory>
using namespace std;
class Movement {
public:
virtual void move() = 0;
virtual unique_ptr<Movement> movement() const = 0;
};
class Walk : public Movement {
public:
void move() { cout << "walking"; }
unique_ptr<Movement> movement() const { return make_unique<Walk>(); }
};
class Run : public Movement {
public:
void move() { cout << "run"; }
unique_ptr<Movement> movement() const { return make_unique<Run>(); }
};
class Animal {
public:
virtual void print() = 0;
virtual unique_ptr<Animal> animal() const = 0;
};
class Human : public Animal {
public:
void print() { cout << "Human"; }
unique_ptr<Animal> animal() const { return make_unique<Human>(); }
};
class Lion : public Animal {
public:
void print() { cout << "Lion"; }
unique_ptr<Animal> animal() const { return make_unique<Lion>(); }
};
class Model {
unique_ptr<Animal> animal;
unique_ptr<Movement> movement;
public:
Model(const Animal& animal = Human(), const Movement& movement = Walk()) {
this->animal = animal.animal();
this->movement = movement.movement();
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first = Model(), second = Model(Lion(), Run());
first.print();
cout << endl;
second.print();
return 0;
}
Is your problem the compile error? There are multiple ways to address the compile error, but given that your question is about inheriting from abstract classes, I will focus on that.
First, as provided, your Animal class is not an abstract class. An abstract class cannot be instantiated because all its methods are pure virtual. In C++, pure virtual functions are designated by the virtual keyword prefix, and suffixed by = 0 in their definition. E.g.
...
virtual void print() = 0;
...
The following code is compilable by making your Animal class an abstract class:
#include <iostream>
using namespace std;
class Movement {
public:
virtual void move() = 0;
};
class Walk : public Movement {
public:
void move() { cout << "walking"; }
};
class Run : public Movement {
public:
void move() { cout << "run"; }
};
class Animal {
public:
virtual void print() = 0;
};
class Human : public Animal {
public:
void print() { cout << "Human"; }
};
class Lion : public Animal {
public:
void print() { cout << "Lion"; }
};
class Model {
Animal* animal;
Movement* movement;
public:
Model(Animal* animal = new Human(), Movement* movement = new Walk()) {
this->animal = animal;
this->movement = movement;
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first = Model(),
second = Model(new Lion(), new Run());
first.print();
cout << endl;
second.print();
return 0;
}
Incidentally, your code can also be made compilable by providing an implementation for Animal::print(). The following code is also compilable, but Animal is not an abstract class because it provides an implementation for Animal::print() rather than suffixing it with = 0:
#include <iostream>
using namespace std;
class Movement {
public:
virtual void move() = 0;
};
class Walk : public Movement {
public:
void move() { cout << "walking"; }
};
class Run : public Movement {
public:
void move() { cout << "run"; }
};
class Animal {
public:
virtual void print() {};
};
class Human : public Animal {
public:
void print() { cout << "Human"; }
};
class Lion : public Animal {
public:
void print() { cout << "Lion"; }
};
class Model {
Animal* animal;
Movement* movement;
public:
Model(Animal* animal = new Human(), Movement* movement = new Walk()) {
this->animal = animal;
this->movement = movement;
}
void print() {
cout << "This Model consist of one: ";
animal->print();
cout << ", which is: ";
movement->move();
}
};
int main() {
Model first = Model(),
second = Model(new Lion(), new Run());
first.print();
cout << endl;
second.print();
return 0;
}
Otherwise, conceptually, what you're doing is fine and totally possible in C++: assigning a default value to a base class pointer that's in some function's argument list.
Important: As commenters have correctly pointed out, the pattern you have coded is dangerous: your interface is such that a user can optionally provide an Animal instance. The problem is: if the Model creator does, then it can be reasonably argued that he rightly owns the object. If he does not, then your constructor will create a new Animal instance, but neither does Model take ownership of the object, nor does it provide an interface by which the user can take ownership of the new Animal instance. This therefore creates a memory leak. Equally, the code hazard, is ambiguous ownership of the Animal instance used in the Model constructor.
I am pretty new to C++ and I have a doubt on templates and polymorphism. So, I was making basic funcs with templates but then I thought that I wanna work with classes and try to do some inheriting. So can someone properly guide me?
I have tried a little only and I just got errors. I really am new so I don't know a lot... :P
Here's the code I have typed till now:
template <class temp>
class car{
public:
temp colour;
temp *ptcs = &colour;
temp setChar(temp a){
*ptcs = a;
}
virtual void sayChar()=0;
};
class lambo : public car<string>{
public:
void sayChar(){
cout << "My characteristic : " << *ptcs << endl;
}
};
class chiron : public car<string>{
public:
void sayChar(){
cout << "My characteristic : " << *ptcs << endl;
}
};
int main(){
}
I expect to inherit from car class and add more to it whilst being able to access and run code from both the derived classes in main()
Why the Pointer ptcs? There is no use for it. If you want to access private members of a base in a derived class, write a getter:
#include <string>
#include <iostream>
template <class T>
class car {
T colour;
public:
void setChar(T a) { colour = a; }
T getChar() const { return colour; }
};
class lambo : public car<std::string> {
public:
void sayChar() const {
std::cout << "My characteristic : " << getChar() << '\n';
}
};
class chiron : public car<std::string> {
public:
void sayChar() const {
std::cout << "My characteristic : " << getChar() << '\n';
}
};
int main()
{
lambo foo;
foo.setChar("red");
foo.sayChar();
chiron bar;
bar.setChar("blue");
bar.sayChar();
}
BTW, the search term you might be looking for is "Curiously recurring template pattern".
I'm using multiple inheritance in C++ and extending base methods by calling their base explicitly. Assume the following hierarchy:
Creature
/ \
Swimmer Flier
\ /
Duck
Which corresponds to
class Creature
{
public:
virtual void print()
{
std::cout << "I'm a creature" << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
void print()
{
Creature::print();
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
void print()
{
Creature::print();
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer
{
public:
void print()
{
Flier::print();
Swimmer::print();
std::cout << "I'm a duck" << std::endl;
}
};
Now this presents a problem - calling the duck's print method calls its respective base methods, all of which in turn call the Creature::print() method, so it ends up being called twice-
I'm a creature
I can fly
I'm a creature
I can swim
I'm a duck
I would like to find a way to make sure the base method is called only once. Something similar to the way virtual inheritance works (calling the base constructor on the first call, then only assigning a pointer to it on successive calls from other derived classes).
Is there some built-in way to do this or do we need to resort to implementing one ourselves?
If so, how would you approach this?
The question isn't specific to printing. I wondered if there's a mechanism for extending base methods and functionality while keeping the call order and avoiding the diamond problem.
I understand now that the most prominent solution would be to add helper methods, but I just wondered if there's a "cleaner" way.
Most likely this is a XY problem. But ... just don't call it twice.
#include <iostream>
class Creature
{
public:
virtual void identify()
{
std::cout << "I'm a creature" << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
virtual void identify() override
{
Creature::identify();
tell_ability();
std::cout << "I'm a swimmer\n";
}
virtual void tell_ability()
{
std::cout << "I can swim\n";
}
};
class Flier : public virtual Creature
{
public:
virtual void identify() override
{
Creature::identify();
tell_ability();
std::cout << "I'm a flier\n";
}
virtual void tell_ability()
{
std::cout << "I can fly\n";
}
};
class Duck : public Flier, public Swimmer
{
public:
virtual void tell_ability() override
{
Flier::tell_ability();
Swimmer::tell_ability();
}
virtual void identify() override
{
Creature::identify();
tell_ability();
std::cout << "I'm a duck\n";
}
};
int main()
{
Creature c;
c.identify();
std::cout << "------------------\n";
Swimmer s;
s.identify();
std::cout << "------------------\n";
Flier f;
f.identify();
std::cout << "------------------\n";
Duck d;
d.identify();
std::cout << "------------------\n";
}
Output:
I'm a creature
------------------
I'm a creature
I can swim
I'm a swimmer
------------------
I'm a creature
I can fly
I'm a flier
------------------
I'm a creature
I can fly
I can swim
I'm a duck
------------------
We can let the base class keep track of the attributes:
#include <iostream>
#include <string>
#include <vector>
using namespace std::string_literals;
class Creature
{
public:
std::string const attribute{"I'm a creature"s};
std::vector<std::string> attributes{attribute};
virtual void print()
{
for (auto& i : attributes)
std::cout << i << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
Swimmer() { attributes.push_back(attribute); }
std::string const attribute{"I can swim"s};
};
class Flier : public virtual Creature
{
public:
Flier() { attributes.push_back(attribute); }
std::string const attribute{"I can fly"s};
};
class Duck : public Flier, public Swimmer
{
public:
Duck() { attributes.push_back(attribute); }
std::string const attribute{"I'm a duck"s};
};
int main()
{
Duck d;
d.print();
}
Likewise, if it is not just printing we're after, but rather the function calls, then we could let the base class keep track of the functions:
#include <iostream>
#include <functional>
#include <vector>
class Creature
{
public:
std::vector<std::function<void()>> print_functions{[this] {Creature::print_this(); }};
virtual void print_this()
{
std::cout << "I'm a creature" << std::endl;
}
void print()
{
for (auto& f : print_functions)
f();
}
};
class Swimmer : public virtual Creature
{
public:
Swimmer() { print_functions.push_back([this] {Swimmer::print_this(); }); }
void print_this()
{
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
Flier() { print_functions.push_back([this] {Flier::print_this(); }); }
void print_this()
{
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer
{
public:
Duck() { print_functions.push_back([this] {Duck::print_this(); }); }
void print_this()
{
std::cout << "I'm a duck" << std::endl;
}
};
int main()
{
Duck d;
d.print();
}
An easy way is to create a bunch of helper classes that mimick the inheritance structure of your main hierarchy and do all the printing in their constructors.
struct CreaturePrinter {
CreaturePrinter() {
std::cout << "I'm a creature\n";
}
};
struct FlierPrinter: virtual CreaturePrinter ...
struct SwimmerPrinter: virtual CreaturePrinter ...
struct DuckPrinter: FlierPrinter, SwimmerPrinter ...
Then each print method in the main hierarchy just creates the corresponding helper class. No manual chaining.
For maintainability you can make each printer class nested in its corresponding main class.
Naturally in most real world cases you want to pass a reference to the main object as an argument to the constructor of its helper.
Your explicit calls to the print methods form the crux of the issue.
One way round this would be to drop the print calls, and replace them with say
void queue(std::set<std::string>& data)
and you accumulate the print messages into the set. Then it doesn't matter those functions in the hierarchy get called more than once.
You then implement the printing of the set in a single method in Creature.
If you want to preserve the order of printing, then you'd need to replace the set with another container that respects the order of insertion and rejects duplicates.
If you want that middle class method, do not call the base class method. The easiest and simplest way is to extract extra methods, and then reimplementing Print is easy.
class Creature
{
public:
virtual void print()
{
std::cout << "I'm a creature" << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
void print()
{
Creature::print();
detailPrint();
}
void detailPrint()
{
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
void print()
{
Creature::print();
detailPrint();
}
void detailPrint()
{
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer
{
public:
void print()
{
Creature::Print();
Flier::detailPrint();
Swimmer::detailPrint();
detailPrint();
}
void detailPrint()
{
std::cout << "I'm a duck" << std::endl;
}
};
Without details what is your actual problem is, it hard to come up with a better solution.
Use:
template<typename Base, typename Derived>
bool is_dominant_descendant(Derived * x) {
return std::abs(
std::distance(
static_cast<char*>(static_cast<void*>(x)),
static_cast<char*>(static_cast<void*>(dynamic_cast<Base*>(x)))
)
) <= sizeof(Derived);
};
class Creature
{
public:
virtual void print()
{
std::cout << "I'm a creature" << std::endl;
}
};
class Walker : public virtual Creature
{
public:
void print()
{
if (is_dominant_descendant<Creature>(this))
Creature::print();
std::cout << "I can walk" << std::endl;
}
};
class Swimmer : public virtual Creature
{
public:
void print()
{
if (is_dominant_descendant<Creature>(this))
Creature::print();
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
void print()
{
if (is_dominant_descendant<Creature>(this))
Creature::print();
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer, public Walker
{
public:
void print()
{
Walker::print();
Swimmer::print();
Flier::print();
std::cout << "I'm a duck" << std::endl;
}
};
And with Visual Studio 2015 the output is:
I'm a creature
I can walk
I can swim
I can fly
I'm a duck
But is_dominant_descendant does not have a portable definition. I wish it were a standard concept.
You are asking for something like inheritance on a function level that automatically calls the inherited function and just adds more code. Also you want it to be done in a virtual way just like class inheritance. Pseudo syntax:
class Swimmer : public virtual Creature
{
public:
// Virtually inherit from Creature::print and extend it by another line of code
void print() : virtual Creature::print()
{
std::cout << "I can swim" << std::endl;
}
};
class Flier : public virtual Creature
{
public:
// Virtually inherit from Creature::print and extend it by another line of code
void print() : virtual Creature::print()
{
std::cout << "I can fly" << std::endl;
}
};
class Duck : public Flier, public Swimmer
{
public:
// Inherit from both prints. As they were created using "virtual function inheritance",
// this will "mix" them just like in virtual class inheritance
void print() : Flier::print(), Swimmer::print()
{
std::cout << "I'm a duck" << std::endl;
}
};
So the answer to your question
Is there some built-in way to do this?
is no. Something like this does not exist in C++. Also, I'm not aware of any other language that has something like this. But it is an interesting idea...
Is it possible to do such things in C++14. I have a base class as follows:
#include <iostream>
class AbstractElement;
class ConcreteElement;
class SuperConcreteElement;
class B
{
public:
void bar(AbstractElement*)
{
std::cout << "Abstract element" << std::endl;
}
void bar(ConcreteElement*)
{
std::cout << "Concrete element" << std::endl;
}
void bar(SuperConcreteElement*)
{
std::cout << "Super concrete element" << std::endl;
}
};
class AbstractElement
{
public:
virtual void foo() = 0;
};
class ConcreteElement : public AbstractElement
{
private:
B _b;
public:
void foo()
{
_b.bar(this); //1
}
};
class SuperConcreteElement : public AbstractElement
{
private:
B _b;
public:
void foo()
{
_b.bar(this); //2
}
};
int main()
{
AbstractElement *e = new ConcreteElement();
e -> foo(); //Prints Concrete element
}
As you can see at //1 and //2, the function's body is completely similar. But I can't quite move it into a base class because of depending on the static type of this. In spite of that fact, I wouldn't like to write absolutely the same code every time I need to add one more subclass of AbstractElement. So, I need some kind of mechanism which provides us with the facility to inject code into a function.
As long as marcos are not very desirable solution, I'd like to ask about some tricks that can be done in C++14 for solving such a problem.
Yes, it is possible using CRTP:
#include <iostream>
class AbstractElement;
class ConcreteElement;
class SuperConcreteElement;
class B
{
public:
void bar(AbstractElement*)
{
std::cout << "Abstract element" << std::endl;
}
void bar(ConcreteElement*)
{
std::cout << "Concrete element" << std::endl;
}
void bar(SuperConcreteElement*)
{
std::cout << "Super concrete element" << std::endl;
}
};
class AbstractElement
{
public:
virtual void foo() = 0;
};
template <class T>
class CRTPAbstractElement : public AbstractElement
{
B _b;
public:
virtual void foo()
{
T* t = dynamic_cast<T *>(this);
_b.bar(t);
}
};
class ConcreteElement : public CRTPAbstractElement<ConcreteElement>
{
};
class SuperConcreteElement : public CRTPAbstractElement<SuperConcreteElement>
{
};
int main()
{
AbstractElement *e = new ConcreteElement();
e -> foo(); //Prints Concrete element
}
By adding an intermediate CRTP class we are able to cast a pointer to the base class to a pointer to the derived class. Thus solving the issue of code duplication.