智能指针的多态性
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;
}
这与多态、虚函数或智能指针无关。
您刚刚犯了两个小的印刷错误:
DerivedWrap pDW1();
声明了一个 函数 。删除 ()
.
->
解引用指针,但 pDW1
和 pDW2
都不是函数。请改用 .
。
你那里有一些错别字,应该是:
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;
正如答案所指出的,这是我犯的一个愚蠢的错误,与多态性或智能指针无关。更正后的版本在接受的答案中。
============== 原题 ==================
我正在尝试使智能指针与多态性一起工作。在下面的原型代码中,纯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();
声明了一个 函数 。删除()
.->
解引用指针,但pDW1
和pDW2
都不是函数。请改用.
。
你那里有一些错别字,应该是:
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;