As the answers pointed out, this is a dumb mistake I made that has nothing to do with polymorphism or smart pointer. The corrected version is in the accepted answer.
============== Original question ==================
I am trying to make smart pointer work with polymorphism. In the following prototype code, the implementation for pure virtual function Base::print() should be in the memory block of Derived object. DerivedWrap have access to the pointer to the Derived object.
Why can not DerivedWrap::print() access the function implementation?
using namespace std;
class Base
{
public:
virtual void print() = 0;
};
class Derived : public Base
{
public:
Derived(int in) : i(in) {}
void print() {
cout << "int is " << i << endl;
}
private:
int i;
};
class DerivedWrap
{
public:
DerivedWrap() : DerivedWrap(make_unique<Derived>(2)) {}
DerivedWrap(unique_ptr<Base> pBase) : _pBase(move(pBase)) {}
void print()
{
_pBase->print();
}
private:
unique_ptr<Base> _pBase;
};
int main()
{
DerivedWrap pDW1();
pDW1->print(); // error: request for member ‘print’ in ‘pDW1’, which is of non-class type ‘DerivedWrap()’
DerivedWrap pDW2(make_unique<Derived>(2));
pDW2->print(); // error: base operand of ‘->’ has non-pointer type ‘DerivedWrap’
return 0;
}
You have a couple of issues.
DerivedWrap pDW1(); is a function declaration whose return
type is DerivedWrap. It is not calling its default constructor which you are expecting to. You need simply
DerivedWrap pDW1; // calls the default constructor
// or
// DerivedWrap pDW1{};
pDW1 is simply a DerivedWrap object. Therefore, no need for calling operator->.
You need in short
DerivedWrap pDW1;
pDW1.print();
The same applies to the pDW2. You need
DerivedWrap pDW2(std::make_unique<Derived>(2));
pDW2.print();
Base must-have virtual destructor for the defined behaviour. See more:
When to use virtual destructors?In short, you need
#include <iostream>
#include <memory>
class Base
{
public:
virtual void print() = 0;
virtual ~Base() = default; // provide virtual destructor
};
class Derived /*final*/: public Base
{
public:
// ... other code
void print() override // recommended to override the virtual functions
{
std::cout << "int is " << i << std::endl;
}
private:
int i;
};
class DerivedWrap /* final */
{
public:
// ...other code
void print()
{
_pBase->print();
}
private:
std::unique_ptr<Base> _pBase;
};
int main()
{
DerivedWrap pDW1; // or DerivedWrap pDW1{};
pDW1.print();
DerivedWrap pDW2{ std::make_unique<Derived>(2) };
pDW2.print();
}
As a side note, please do not practice with using namespace std;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With