5

I have this code:

#include <iostream>
#include <string>
using namespace std;

struct Flower
{
    virtual string str() = 0;
};

struct Rose : Flower
{
    string str() override { return "A rose"; }
};

struct RedFlower : Flower
{
    Flower& flower;
    RedFlower(Flower& flower) : flower{ flower } {}
    string str() override { return flower.str() + " that is red"; }
};

int main()
{
    Rose rose;
    RedFlower red_rose{ rose };
    RedFlower red_red_rose{ red_rose };
    RedFlower red_red_red_rose{ red_red_rose };
    cout << rose.str() << endl;
    cout << red_rose.str() << endl;
    cout << red_red_rose.str() << endl;
    cout << red_red_red_rose.str() << endl;
}

It prints out

A rose
A rose that is red
A rose that is red
A rose that is red

Shouldn't it print out

A rose
A rose that is red
A rose that is red that is red
A rose that is red that is red that is red

??? Why is it not printing out what it should? Does the compiler optimise away the calls or is the class hierarchy lost along the away? I don't seem to pin point what exactly it is that I'm missing. I know something must be wrong with my code. I believe dynamic polymorphism is lost somewhere in the call stack... ?

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 2
    Hint: Your constructor is not actually called. Do you know about copy constructors? – Lukas-T Oct 23 '20 at 16:56
  • 3
    In the meantime I'm voting to reopen, because it's not that obvoious what is happening here and for a beginner even a debugger will not help all that much. But I guess it's easier to just tell people to solve their propblems themselves than just answering or at least leving some comment... – Lukas-T Oct 23 '20 at 16:57
  • yeah... I can't answer my own question, so I'm going answer it here. I forgot I was using references, which means I actually got just two objects: the first two, a Rose and a RedRose. The other RedRoses were just referencing the second RedRose. BTW, I know how use a debugger and I already tried it before asking the question..... – Saitama10000 Oct 23 '20 at 16:59
  • It's been reopened, so you can answer the question now :) – cigien Oct 23 '20 at 17:02
  • I'm learning the Decorator design pattern. I know about copy constructors. Thanks for the upvote. – Saitama10000 Oct 23 '20 at 17:04
  • @cigien Thanks :) – Lukas-T Oct 23 '20 at 17:07
  • @churill Turns out I don't know about copy constructors. – Saitama10000 Oct 23 '20 at 17:15

1 Answers1

3

the problem here is, that the compiler automatically generates a copy- constructor with the following signature:

RedFlower(RedFlower const &)

That constructor is being called instead of your custom one. One solution is to add an explicit cast to Flower &:

Rose rose;
RedFlower red_rose{ rose };
RedFlower red_red_rose{ static_cast<Flower &>(red_rose) };
RedFlower red_red_red_rose{ static_cast<Flower&>(red_red_rose) };
Lukas-T
  • 11,133
  • 3
  • 20
  • 30