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

============== 原始问题 ==================

我正在尝试使智能指针与多态一起工作。在下面的原型(prototype)代码中,纯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;
}

最佳答案

你有几个问题。

  • 这个 DerivedWrap pDW1(); 是一个函数声明,它的返回
    类型是 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;

    关于c++ - 智能指针的多态性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/62457465/

    10-08 22:51