Say I have a class A. Class B and class C are both children classes of A.
Would it be a flawed inheritance design if the class C needed to include B?
edit: an example
Say I have a parent class called Trip that has two attributes : start and end. My first inherited class (B) from A is called SimpleTrip, it has an added attribute called transport (so in total : start, end and transport). My second inherited class (C) from A is called CompoundTrip, it has two added attributes an array of SimpleTrips and a number of trips (so it total : start, end, array of SimpleTrips, number of trips). A compound trip is a "group" of simple trips, but is still a trip.
Have a look at this and try to answer "What does c.a() print" without running the program, then try and run it.
#include <iostream>
struct A {
virtual void a() {
std::cout << "a" << std::endl;
}
};
struct B : A {
virtual void a() override {
std::cout << "b" << std::endl;
};
};
struct C : A, B {
};
int main() {
C c;
c.a();
}
https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem
Related
Is there a way to write an abstract base class that looks like it's forcing an implementer to choose among a myriad of pure virtual functions?
The abstract base classes I'm writing define a mathematically tedious function, and request that the deriving code define only building block functions. The building block functions can be generalized to take on more arguments, though. For example, in the code below, it might "make sense" to allow another_derived::first() to take three arguments. The "mathematically tedious" part of this is the multiplication by 3. Unsurprisingly, it won't allow won't compile unless I comment out the creation of d2. I understand why.
One option is to create different base classes. One would request a single parameter function to be defined, and the other would request a two parameter function to be defined. However, there would be an enormous amount of code being copy and pasted between the two base class' definition of final_result(). This is why I'm asking, so I don't write WET code.
Another option would be to have one pure virtual function, but change the signature so that its implementation can do either of these things. I want to explore this, but I also don't want to start using fancier techniques so that it puts a barrier to entry on the type of people trying to inherit from these base classes. Ideally, if the writers of the base class could get away with barely knowing any c++, that would be great. Also, it would be ideal if the inheritors didn't even have to know about the existence of related classes they could be writing.
#include <iostream>
class base{
public:
virtual int first(int a) = 0;
int final_result(int a) {
return 3*first(a);
}
};
class derived : public base {
public:
int first(int a) {
return 2*a;
}
};
class another_derived : public base {
public:
int first(int a, int b) {
return a + b;
}
};
int main() {
derived d;
std::cout << d.final_result(1) << "\n";
//another_derived d2; // doesn't work
return 0;
}
Not sure it matches exactly what you want, but with CRTP, you might do something like:
template <typename Derived>
struct MulBy3
{
template <typename... Ts>
int final_result(Ts... args) { return 3 * static_cast<Derived&>(*this).first(args...); }
};
class derived : public MulBy3<derived> {
public:
int first(int a) { return 2*a; }
};
class another_derived : public MulBy3<another_derived > {
public:
int first(int a, int b) { return a + b; }
};
With usage similar to
int main() {
derived d;
std::cout << d.final_result(1) << "\n";
another_derived d2;
std::cout << d2.final_result(10, 4) << "\n";
}
Demo
I have a hierarchy of classes:
class Base
{
public:
Base():a{5}{}
virtual ~Base(){};
int a;
};
class Derived : public Base
{
public:
Derived():b{10}{}
int b;
};
I then have a class template that operates on whatever type it is instanciated with:
template<typename T>
class DoStuff
{
public:
DoStuff():val{}{}
virtual ~DoStuff(){};
virtual void printDoStuff() = 0;
T getVal(){return val;};
private:
T val;
};
class DoStuffWithInt : public DoStuff<int>
{
public:
virtual void printDoStuff() override {cout << "val = " << getVal() << endl;}
};
class DoStuffWithBase : public DoStuff<Base>
{
public:
virtual void printDoStuff() {cout << "a = " << getVal().a << endl;}
};
Now I would like to have a hierarchy of class like this:
class DoStuffWithBase : public DoStuff<Base>
{
public:
virtual void printDoStuff() {printVal(); cout << "a = " << getVal().a << endl;}
};
// Wrong and will not compile, trying to make a point
class DoStuffWithDerived : public DoStuffWithBase<Derived>
{
public:
void printDoStuff() override {DoStuffWithBase::printDoStuff(); cout << "b = " << getVal().b << endl;}
};
Basically I would like to have DoStuffWithBase that operates on a base be extended so that I can reuse its functions, but the extended class DoStuffWithDerived should operate on a Derived type.
I managed to get something working by templating DoStuffWithBase with a pointer to Base and extending it:
template <class T>
static void deleteIfPointer(const T& t)
{
std::cout << "not pointer" << std::endl;
}
template <class T>
static void deleteIfPointer(T* t)
// ^
{
std::cout << "is pointer" << std::endl;
delete t;
}
template<typename T>
class DoStuff
{
public:
DoStuff():val{}{}
DoStuff(const T& value):val{value}{};
virtual ~DoStuff(){deleteIfPointer(val);}
virtual void printDoStuff() = 0;
T getVal(){return val;};
private:
T val;
};
class DoStuffWithBase : public DoStuff<Base*>
{
public:
// New base
DoStuffWithBase(): DoStuff(new Base()){}
DoStuffWithBase(Base* b) : DoStuff(b){}
virtual void printDoStuff() {printVal(); cout << "a = " << getVal()->a << endl;}
};
class DoStuffWithDerived : public DoStuffWithBase
{
public:
// New derived
DoStuffWithDerived(): DoStuffWithBase(new Derived()){}
void printDoStuff() override {DoStuffWithBase::printDoStuff(); cout << "b = " << static_cast<Derived*>(getVal())->b << endl;}
};
It works but there are several things I don't like:
The code is a lot more complicated, when 99% of the time, I won't need to extend a DoStuffWithX class, I will just use DoStuffWithInt, DoStuffWithClass, DoStuffWithAnotherClass etc... Here I had to add several constructors, a special case destructor and so on.
I have to use pointers and manage them (static_cast when needed, deletion...), all in order to avoid slicing and get the right type. Also, DoStuff::val should theorically not be null, but with a pointer there is no way I can prevent that (or atleast I don't know one). Maybe using smart pointers would help a bit here ? I am not super familiar with them.
I have to manage cases where T is a pointer and when it is not. For example, the deleteIfPointer function above, but also switching between . and -> and probably more.
Is there any simpler way to achieve what I am trying to do ? A design pattern or something else ? Am I stuck with my solution and is it somewhat good ?
Edit: I tried to implement it with std::variant as in #Tiger4Hire's answer:
class Derived : public Base
{
public:
Derived():b{10}{}
int b;
};
class Derived2 : public Base
{
public:
Derived2():c{12}{}
int c;
};
using DerivedTypes = std::variant<Derived, Derived2>;
struct VariantVisitor
{
void operator()(Derived& d)
{
d.b = 17;
}
void operator()(Derived2& d)
{
d.c = 17;
}
};
class DoStuffWithVariant : public DoStuff<DerivedTypes>
{
public:
void handleBasePart(Base& base)
{
cout << "a = " << base.a << endl;
base.a = 10;
}
virtual void printDoStuff() override
{
auto unionVal_l = getVal();
if (std::holds_alternative<Derived>(unionVal_l))
{
std::cout << "the variant holds a Derived!\n";
auto& derived_l = std::get<0>(unionVal_l);
cout << "b = " << derived_l.b << endl;
handleBasePart(derived_l);
}
else if (std::holds_alternative<Derived2>(unionVal_l))
{
std::cout << "the variant holds a Derived2!\n";
auto& derived2_l = std::get<1>(unionVal_l);
cout << "c = " << derived2_l.c << endl;
handleBasePart(derived2_l);
}
std::visit(VariantVisitor{}, unionVal_l);
}
};
What I like about it:
I don't have to use pointers.
I feel the code is less tricky, easier to understand.
What I don't like about it:
The code is all in one place and it deals with all the possible Derived types (and even the Base type) at once whereas with inheritance, classes are more specialized, you can really look at a class and directly know what it does, what it overrides etc... On the other hand one could argue that it means the algorithm is in one place instead of dispatched all over the classes hierarchy.
You can't have an abstract base class as your interface.
All in all it is a really good alternative, but I am still wondering if there is a simpler way to implement dynamic polymorphism ? Do you necessarily have to resort to (base class) pointers with dynamic polymorphism ? Are std::variant the way to go now ?
Edit2: 2 other drawbacks with variants that I didn't notice at first:
All your derived class and your base class have to be defined in the same library. Clients can't easily add a new Derived class since it would mean modifying the variant and they might not have access to it.
On the project I am working on, base classes are defined in one library, and are derived in other independant "sub" libraries. So if I try to use variant in my main library, it won't be able to access the Derived types in the sub libraries, which is a major issue.
If your base class implenting the variant (DoStuff here) has other members, when you call std::visit on the variant, you might have to also embark the needed other members of DoStuff. I think you should be able to use lambdas to capture them, but still, it's a lot less straightforward than using them directly as in the case of inheritance.
Your core problem is that you cast away your type information.
C++ will always call the right function, if it knows the correct type. This is why the pattern of pointer-to-base is almost always an anti-pattern (even though it is often taught as the "C++" way to do things).
Modern C++-style is to hold things as strongly-typed pointers, and cast them to the base pointer object, only when calling a function that takes a base-pointer as a parameter.
The standard supports this way of working by providing std::variant. Thus rather than
std::vector<Base*> my_list_of_things;
my_list_of_things.push_back(new Derived); // casting away type is bad
You start with
using DerivedTypes = std::variant<std::unique_ptr<Derived1>,
std::unique_ptr<Derived2>/*,etc*/>;
std::vector<DerivedTypes> my_list_of_things;
Now you can iterate over the list, calling a function which takes a pointer-to-base, casting away the type information only during the call.
You can also visit the members of the list, with a function (often a lambda) that knows exactly the type it is working on.
So you get the best of both worlds!
This does assume you have access to C++17 or above though, also that you are not working with code that is a library (compiled) but allows the library user to make their own classes. For example, libraries like Qt can't use this way of working.
If you don't have access to C++17, you may find curiously recursing templates fit much of what you are doing. (This is a controversial pattern though, as it is ugly and confusing)
I'm trying to make an inherited class access the self class default content.
The code is below (Note that array declared isn't the same size between parent and child class)
#include <iostream>
class A {
public:
int number[2] = {1,2};
A(){};
void show() {std::cout << "Number: " << number[0] << ", " << number[1] << "\n"; };
};
class B : public A {
public:
int number[3] = {5,6,7};
B() {};
// With this code below it works but I don't want to code the same function on every child class
//void show() {std::cout << "Number: " << number[0] << ", " << number[1] << "\n"; };
};
int main() {
A obj_a;
obj_a.show();
B obj_b;
obj_b.show();
}
Which outputs this:
Number: 1, 2
Number: 1, 2
Expected output should be:
Number: 1, 2
Number: 5, 6
Anyone can help?
Note: The code should be used on arduino, I used std::cout just for sharing to you.
EDIT:
I want to make an array of objects so it can be easily changed the size, and in other parts of the code, I can simply for loop of the array and do whatever is needed.
Also the purpose for subclasses is because I have different "numbers" and his sizes. For example, imagine a vehicle which is the super class, that has 2 child classes named "auto" and "moto", auto has int wheels[4] = {...} and moto int wheels[2] = {...}
A::number and B::number are two completely independent class members, that have nothing to do with each other.
A::show() only knows about members of A, and only knows about A::number. It doesn't know anything about B even if it's a superclass of an instance of B.
Your C++ textbook will explain what virtual functions are, and how to use them. The simplest solution is to add a virtual method in A, let's call it get_number, that returns an int *, and the get_number function simply returns number:
class A {
// ...
virtual int *get_number()
{
return number;
}
};
In B the virtual function gets overridden, and it returns a pointer to its own class's number.
class B {
// ...
int *get_number() override
{
return number;
}
};
Then, your show() method calls get_number() to get a pointer to the appropriate array. See your C++ textbook for a complete discussion of virtual class methods.
You are experiencing name hiding - name in inner scope shadows the same symbol name in outer scope. In your case B::number hides A::number.
C++ does not support "virtual" member variables, so you cannot redefine number. My suggestion is to not use inheritance if there should indeed be just one array. Because then B is not really an A.
Or at least you could generalize the A class to contain arbitrarly long array. There are multiple ways doing that:
std::vector A::number member with a constructor A(std::size_t n) accepting the size.
Make A a class template with template<std::size_t N> argument denoting the size, then you can use std::array<int,N> number; member variable.
Pass the array to the base class for ownership.
Another option is to make show virtual and override it in the derived class with custom printing, but then you will still be left with two arrays, which is a clear design flaw.
I'm currently playing around with CRTP and am coming across the issue of a member variable in the derived class being corrupted aka having a garbage value (there are currently 4 levels of polymorphism, with the top most base class called "A" and the bottom most derived class called "D").
Here is some code that displays an example of this issue:
//A.hpp
template <class TB>
class A {
public:
A();
void CRTP_func();
};
template <class TB>
A<TB>::A() {
std::cout << "A constructor called!" << std::endl;
}
template<class TB>
void A<TB>::CRTP_func() {
std::cout << "CRTP_index called in A" << std::endl;
static_cast<TB*>(this)->CRTP_func2();
}
//B.hpp
#include "A.hpp"
#include <vector>
template<class TC>
class B : public A<B<TC>>
{
public:
B();
void CRTP_func2();
};
template<class TC>
B<TC>::B() {
std::cout << "B constructor called!" << std::endl;
}
template<class TC>
void B<TC>::CRTP_func2() {
std::cout << "CRTP_func called in B" << std::endl;
static_cast<TC*>(this)->CRTP_func3();
}
//C.hpp
#include "B.hpp"
template<class TD>
class C : B<C<TD>> {
public:
C();
void CRTP_func3();
int x;
};
template<class TD>
C<TD>::C() {
std::cout << "C constructor called" << std::endl;
}
template<class TD>
void C<TD>::CRTP_func3() {
std::cout << "CRTP_index3 called in C" << std::endl;
static_cast<TD*>(this)->CRTP_func4();
}
//D.hpp
#include "C.hpp"
class D : C<D> {
public:
D();
bool onInit();
void CRTP_func4();
C<D> top;
int y = 0;
};
D::D() {
std::cout << "D constructor called!" << std::endl;
}
bool D::onInit() {
std::cout << "D onInit called!" << std::endl;
y = 5;
return true;
}
void D::CRTP_func4() {
std::cout << y << std::endl;
std::cout << "CRTP_index4 called in D! " << std::endl;
}
//main.hpp
int main {
D * D_ptr = new D();
D_ptr->onInit();
D_ptr->top.CRTP_func3();
return 0;
}
As you can see A is the base class while D is the derived class as such:
A<B<C<D>>>
The output for this program is as follows:
A constructor called!
B constructor called!
C constructor called
A constructor called!
B constructor called!
C constructor called
D constructor called!
D onInit called!
CRTP_index3 called in C
-33686019
CRTP_index4 called in D!
The value -33686019 is printed out in D.hpp where the value y is printed and is set to 5 upon initialization. After a little digging I checked the value in main.cpp and it is set to 5 even after making these CRTP calls, yet a garbage value gets printed.
After some more debugging I realized that removing the line
int x;
in B.hpp solves this problem, so I think the issue has to do with some misalignment, but I am not sure why this would happen. Does anyone know why this would happen or how to fix it?
Sorry for the long post and ambiguous code, I tried to remove most of the complexity and simplify the code as much as possible for the sake of the post.
UPDATE:
Thanks to the comments below I figured out how to fix my issue. Instead of using D::top, a better approach is to create a pointer in the main file as such:
C<D> * C_ptr = static_cast<C<D>*>(D_ptr);
and then call CRTP_func3() from there as such:
C_ptr->CRTP_func3();
This works as intended.
You call the function CRTP_func3() on an object with static type C<D> (D::top). The function C<D>::CRTP_func3() does a static_cast<D*>(this) but the object doesn't have the expected type. Thus, the behavior is undefined.
The most fundamental problem you have, logic-wise, is that you are expecting D_Ptr and D_Ptr->top to have the same value for y (you said you expected 5). D_Ptr->top is an entirely different instance and even if it ultimately derived from D, would have its own copy of y.
Then, D derives from C, so it's fundamentally impossible for a C to derive from D, regardless of template insanity. That's the assumption you make by calling CRTP_func4 on a this pointer of C.
Furthermore, that same function call assumes the template type TD is an instance of D. That function call exists within C, and that's an insane assumption for C to make--although I believe it happens to be correct in this case. (that one the compiler would catch if it weren't)
Lastly regarding crtp: consider rejecting Satan and all his ways.
But seriously, there's obviously no complete stand-in, but I think you'll find if you fully consider the power of interfaces (or pure abstract classes in C++), you may be able to find a way around using it. And have (nearly) the same performance... I don't know your specific problem, of course, but I'd highly recommend taking a long, careful look at this article https://en.wikipedia.org/wiki/Composition_over_inheritance
Particularly look at the 2nd example code block, that's written in C# (where interface would be a pure abstract class in C++). Give some thought to whether this pattern could help you.
I'm implementing a reference counting base class and would like to set uniqe number for each object being created which inherits that interface.
here is a code snippet from that class:
HEADER:
class Object
{
const long long int object_id;
public:
Object();
virtual ~Object();
};
CPP:
Object::Object() : object_id(reinterpret_cast<long long int>(&object_id))
{
}
I'm corious if that's safe approach or not, if not why not?
I didn't use rand and srand function because of 2 reasons:
srand AFAIK is best to use only one time in a project to make random numbers as much as possible random.
this approach is more precise since two objects can not share same memory location.
please advice me.
EDIT:
At which point is member object_id created? inside of constructor or outside (before initializatin list or after) hm hm?
thanks alot!
It's not a safe approach. You haven't considered non-virtual multiple inheritance. It's rare, but legal.
class A : public Object {};
class B : public Object {};
class C : public A, public B {}; // Now C has *two* IDs!
OK this is first time I'm answering to my own question but here is what I did to make unique_id work.
//this is base class which only hold the id and may be inherited only by Object class
struct object_id
{
//friend class Object;
//protected: MAKE IT PUBLIC FOR TESTING PURPOSES! FOR NOW
int id;
object_id() : id(reinterpret_cast<int>(&id)) { } //id will be 100% uniqe
};
//this class inherits virtualy so the id member will be in each derived class only once!
class Object : virtual public object_id //INHERIT PRIVATE LATER, now it's public for testing!
{
public:
Object(){}
virtual ~Object(){}
};
TEST:
//now let's make some diamod inheritance to se if it work:)
class a: public Object{};
class b: public Object{};
class c: public a,b{};
//now let's test it:
int main()
{
c obj;
c ss;
c dd;
cout << endl << obj.id << endl << ss.id << endl << dd.id << endl;
cin.ignore();
return 0;
}
This works just fine and every object now has it's own unique ID!