基础抽象类:
class Satellite
{
public:
Satellite();
virtual void center()=0;
virtual ~Satellite(){}
};
第一个派生类
class Comm_sat:public Satellite
{
public:
Comm_sat();
void center() override{cout << "comm satellite override\n";}
};
第二个派生类
class Space_station:public Satellite
{
public:
Space_station();
void center() override{cout << "space station override\n";}
};
函数的指针版本
void f(Satellite* ms){
ms->center();
delete ms;
}
int main()
{
Comm_sat* cs = new Comm_sat;
Space_station* ss = new Space_station;
f(cs);
f(ss);
}
new
中使用main()
创建的对象在f()
中被正确销毁,对吗?
功能的参考版本
void f(Satellite& ms){
ms.center();
}
int main()
{
Comm_sat cs;
Space_station ss;
f(cs);
f(ss);
}
参考版本更好吗?
此外,我尝试使用unique_ptr
,但是,我收到了错误
void f(Satellite* ms){
ms->center();
}
int main()
{
unique_ptr<Comm_sat> cs{new Comm_sat};
unique_ptr<Space_station> ss{new Space_station};
f(cs);
f(ss);
}
错误:无法将参数
std::unique_ptr<Comm_sat>
的{{1}}转换为Satellite*
至1
错误:输入void f(Satellite*)
的{{1}}参数,预期指针class std::unique_ptr<Comm_sat>
;
其他派生类的错误相同。
答案 0 :(得分:4)
参考版本更好吗?
是的,虽然更好的方法是将“指针版本更糟糕”。指针版本的问题是你传递一个有效的指针,并在函数返回时获得一个悬空指针。这不直观,如果有人修改您的代码,认为您忘记删除cs
中的ss
和main
,并未意识到f
已删除,则会导致维护问题。它的论点。
在这方面,使用引用的版本要好得多,因为资源是自动管理的。您的代码的读者不需要跟踪释放cs
和ss
内存的位置,因为分配和释放会自动发生。
我尝试使用
unique_ptr
,但是,我收到了错误
没有从std::unique_ptr<T>
到T*
的隐式转换。如果要传递原始指针,则需要调用get()
:
f(cs.get());
f(ss.get());
答案 1 :(得分:3)
new
中使用main()
创建的对象在f()
中被正确销毁,对吗?
他们被摧毁,并且正确清理,是的。 &#34;妥&#34;虽然是一个延伸,因为所有这些手动 - 新 - 删除 - 原始指针的东西都很糟糕。
unique_ptr
不适合您的原因是......它是unique_ptr
,而不是原始指针。你不能把它作为原始指针传递。
尝试
void f(Satellite* ms){
ms->center();
}
// ...
f(cs.get());
或更好,除非您确实需要有时通过nullptr
,
void f(Satellite& ms){
ms.center();
}
// ...
f(*cs);
或者最重要的是,因为您根本没有理由要求动态分配:
void f(Satellite& ms);
// ...
{
Comm_sat cs;
f(cs);
} // no new, no delete, cs goes out of scope here