0

This is my code:

class SimpleProduct {
    char look = 'x';
    string name = "Undefined";
    string type = "Undefined";
    string description = "Undefined";
public:
    char getLook() const {return look;}
    string getType() const {return type;}
    string getName() const {return name;}
    string getDescription() const {return description;}
    SimpleProduct(char look = 'x', string &&name = "Undefined", string &&type = "Undefined", string &&description = "Undefined");
    string toString() const;
};

class TallProduct : public SimpleProduct {
public:
    TallProduct(char look, string &&name = "Undefined", string &&type = "Undefined", string &&description = "Undefined");
    string toString() const;
};


inline SimpleProduct::SimpleProduct(char look, string &&name, string &&type, string &&description) :
        look(look), name(move(name)), type(move(type)), description(move(description)) {
}

inline string SimpleProduct::toString() const {
    ostringstream ost;
    if (this->getName() == "Space") {
        ost << "";
    } else {
        ost << "Look: " << this->getLook() << ", name: " << this->getName() << ", type: " << this->getType() << ", description: "
            << this->getDescription();
    }
    return ost.str();
};

inline TallProduct::TallProduct(char look, string &&name, string &&type, string &&description){
}

inline string TallProduct::toString() const {
    return "TALL | " + SimpleProduct::toString();
}

And this is my test:

TEST(Test3, TallProduct) {
    SimpleProduct *product = new TallProduct('t', "Fresh sandwich", "sandwich", "check the expiration date");
    ASSERT_EQ("TALL | Look: t, name: Fresh sandwich, type: sandwich, description: check the expiration date",  product->toString());
}

The result I get is always like this:

"Look: x, name: Undefined, type: Undefined, description: Undefined"

while it should be:

"TALL | Look: t, name: Fresh sandwich, type: sandwich, description: check the expiration date"

Can you direct me where did I make a mistake? I guess the wrong part is somewhere around calling method ::tostring, but have no idea how to call TallProduct::toString, instead of SimpleProduct::toString.

galdin
  • 12,411
  • 7
  • 56
  • 71
bartolomo
  • 15
  • 2
  • 7

3 Answers3

1

Your TallProduct constructor does not initialize its base class. Write

inline TallProduct::TallProduct(char look, string &&name, string &&type, string &&description) : 
   SimpleProduct::SimpleProduct(look, std::move(name), std::move(type), std::move(description))
{
}

See delegating constructors.

Futhermore, the functions of your base class are not virtual. That means, a call to product->toString() will always call SimpleProduct::toString since product is of type SimpleProduct *, even though the object pointed to is of type TallProduct. If the functions are declared as virtual, the program will find out at runtime what to call.

Also you must declare the destructor of your base class virtual. Read about that in the above link. Otherwise you invoke undefined behavior.

n314159
  • 4,990
  • 1
  • 5
  • 20
  • Thanks, that solves half of my problem. The other half still stays on getting result `"Look: x, name:..."` instead of `"TALL | Look: t, name:"`. So basically it calls inline `string SimpleProduct::toString() const` instead of `inline string TallProduct::toString() const`. – bartolomo Nov 30 '19 at 13:16
  • As @WhozCraig said above, use [virtual functions](https://en.cppreference.com/w/cpp/language/virtual). I will edit my answer to include that. – n314159 Nov 30 '19 at 13:17
1

The other half of the problem is that: since TallProduct is not initializing SimpleProduct all class variables in SimpleProduct have default values.

char look = 'x';
string name = "Undefined";
string type = "Undefined";
string description = "Undefined";

As such the arguments to the ASSERT_EQ macro are not equal

1

This is a typical case of Polymorphism. Your *product pointer variable is of SimpleProduct type but you have assigned it a TallProduct object and assume that calling product->toString() will call the TallProduct version of toString(). That is not the case.

This is called compile time / static binding. It means during compilation your compiler will bind product->toString() call to the SimpleProduct version of toString() because that is the logical decision right?

But if you define your toString() method as virtual in SimpleProduct and TallProduct then compiler will say, "Okay, I will not bind any method to this call right now and we'll see on runtime which method to actually call depending on the actual type of variable referenced by *product."

Read more about C++ Polymorphism.

Read more about static and dynamic binding Virtual functions (C++ only)

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Syed Ahmed Jamil
  • 1,881
  • 3
  • 18
  • 34