智能指针的多态性

Polymorphism with smart pointer

正如答案所指出的,这是我犯的一个愚蠢的错误,与多态性或智能指针无关。更正后的版本在接受的答案中。

============== 原题 ==================

我正在尝试使智能指针与多态性一起工作。在下面的原型代码中,纯virtual函数Base::print()的实现应该在Derived对象的内存块中。 DerivedWrap 可以访问指向 Derived 对象的指针。

为什么不能DerivedWrap::print()访问函数实现?

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;
}

这与多态、虚函数或智能指针无关。

您刚刚犯了两个小的印刷错误:

  1. DerivedWrap pDW1(); 声明了一个 函数 。删除 ().
  2. -> 解引用指针,但 pDW1pDW2 都不是函数。请改用 .

你那里有一些错别字,应该是:

int main()
{
  DerivedWrap pDW1; // object instantiation, no () needed
  pDW1.print(); //no dereferencing required

  DerivedWrap pDW2(make_unique<Derived>(2));
  pDW2.print(); // again, no dereference required

  return 0;
}

另外请注意,对于多态对象,您需要在基类中使用虚拟析构函数 class。

你有几个问题。

  • 这个 DerivedWrap pDW1(); 是一个 return 的函数声明 类型是 DerivedWrap。它没有调用您期望的默认构造函数。你只需要
    DerivedWrap pDW1;  // calls the default constructor
    // or 
    // DerivedWrap pDW1{};
    
  • 其次,pDW1 只是一个 DerivedWrap 对象。因此,不需要调用operator->。 简而言之,您需要
    DerivedWrap pDW1;
    pDW1.print(); 
    
    这同样适用于pDW2。你需要
    DerivedWrap pDW2(std::make_unique<Derived>(2));
    pDW2.print();
    
  • 最后但同样重要的是,Base 必须具有 virtual 定义行为的析构函数。查看更多: When to use virtual destructors?

总之,你需要

#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();
}

作为旁注,请do not practice with using namespace std;