具有智能指针的多态性

Polymorphism with smart pointer

本文关键字:多态性 指针 智能      更新时间:2023-10-16

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

====

================================我正在尝试使智能指针与多态性一起工作。在下面的原型代码中,纯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析构函数。查看更多: 何时使用虚拟析构函数?

简而言之,您需要

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

作为旁注,请不要练习using namespace std;

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

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

另一个注意事项是,对于多态对象,您将需要在基类中使用虚拟析构函数。

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

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

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