C++ 多态性中的引用和指针

C++ 多态性中的引用和指针,c++,pointers,reference,polymorphism,C++,Pointers,Reference,Polymorphism,基本抽象类: 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";} }; c

基本抽象类:

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";}
};
main()
中使用
new
创建的对象在
f()
中正确销毁,对吗

函数的参考版本

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);
}
void f(Satellite& ms){
    ms.center();
}

int main()
{
    Comm_sat cs;
    Space_station ss;
    f(cs);
    f(ss);
}
参考版本更好吗

此外,我尝试使用
unique\u 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);
}
void f(卫星*ms){
ms->center();
}
int main()
{
独特的{新通信卫星};
独特的{新空间站};
f(cs);
f(ss);
}
错误:无法将参数
1
std::unique\u ptr
转换为
Satellite*
void f(Satellite*)

错误:输入
class std::unique_ptr
参数指定给
delete
,预期指针
delete cs

另一个派生类的错误相同

参考版本更好吗

是的,尽管更好的说法是“指针版本更差”。指针版本的问题在于,您向它传递了一个有效指针,并在函数返回时得到一个悬空指针。这是不直观的,当有人认为您忘记了删除
main
中的
cs
ss
而没有意识到
f
删除了它的参数时,就会导致维护方面的麻烦

在这方面,使用引用的版本要好得多,因为资源是为您自动管理的。代码的读取器不需要跟踪
cs
ss
的内存释放位置,因为分配和释放是自动进行的

我尝试使用
unique\u 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
T*
的隐式转换。如果要传递原始指针,需要调用:

f(cs.get());
f(ss.get());
main()
中使用
new
创建的对象在
f()
中正确销毁,对吗

它们被摧毁了,并且被正确地清理了,是的。“正确”是一种延伸,因为所有这些手动新建和删除原始指针的东西都是糟糕的风格

unique\u ptr
不适合您的原因是。。。它是一个
唯一的\u ptr
,不是原始指针。你不能把它当作一个原始指针来传递

试一试

或者更好,除非您有时确实需要通过
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

void main
是不允许的。如果我理解正确,在任何一种情况下(指针或引用),对象都是在堆上分配的,而不是在堆栈上分配的,对吗?@MiloLu使用引用的版本在堆栈上分配
cs
ss
对象。正如建议的那样,我可以在堆上分配对象,并且仍然通过引用传递
*cs
*ss
。在我看来,地址只是一个地址,不管它在堆上还是在堆栈上。@MiloLu这取决于你。在堆栈上进行分配的一个优点是,您不需要跟踪对象的生存期并调用
delete
。堆栈分配的缺点是,您无法将对象的生存期延长到已分配对象的块的运行时之后。除此之外,堆栈比堆快,这再次使引用版本成为首选?