考虑以下代码:
class Abstract{
public:
virtual void printStuff()=0;
};
class Derived: public Abstract{
public:
void printStuff(){
printf("Stuff\n");
}
};
现在,假设我想创建一个使用抽象类中的 printStuff 方法的函数。在我了解到在 C++ 中只有一种方法是可能的之前,我认为会有两种方法:一种不太明显的指针,一种更明显的方法,类似于您期望对 int、char 等做的事情:
void ptr_function(Abstract* abs){ //non-obvious
abs->printStuff();
}
void non_ptr_function(Abstract abs){ //obvious, analogous to, say, pow(a,b)
abs.printStuff();
}
现在,我明白了在 C++ 中第二个是被禁止的。但是,我并不真正理解这种设计的根本原因。除了作为参数传递的指针与实际对象之外,上述函数看起来不一样吗?
作为后续问题:构建必须“包含”其他抽象类作为字段之一的类的首选方法是什么?如果这个问题的答案也是:“指针”,那么我是否遗漏了什么,或者我是否必须自己跟踪这些对象的生命周期(即手动删除它们)?对于非抽象类,这不是问题,就好像我不使用指针一样,只要该对象超出范围,它就会自动删除(调用析构函数等)。但是,如果我必须使用指针,那么微观管理似乎会花费很多不必要的时间和代码。
有没有更好的方法来解决这个问题?
最佳答案
您不能按值传递抽象类,因为它不能被实例化。在大多数情况下,按值传递无论如何都是错误的(或者至少是非最佳的)。您正在寻找的是通过引用传递:
void ref_function(Abstract & abs)
{
abs.printStuff();
}
当您通过引用传递时,对 ref_function
内的 abs
所做的任何修改都会应用到函数外部存在的同一实例。理想情况下,在您的测试用例中,您希望将对象作为 const Abstract & abs
传递,这将防止对该对象进行任何更改。但是在您的示例中,您需要将 printStuff
标记为 const 以表示它不会更改调用它的对象 - 签名将更改为 virtual void printStuff() const
在回答关于抽象类的所有权应该如何工作的其他问题时。请记住,您实际上不能拥有抽象类的实例,所以您所说的是通过以下方式持有指向某个派生对象的指针其抽象基类的句柄。您可能希望为此使用 std::unique_ptr,因为它会在您的类被销毁时正确删除拥有的对象。
class Abstract
{
public:
virtual void Foo() = 0;
};
class Derived : public Abstract
{
public:
virtual void Foo() override {}
};
class MyClass
{
public:
MyClass();
private:
std::unique_ptr<Abstract> myObject;
};
MyClass::MyClass() : myObject(std::make_unique<Derived>())
{
}
关于c++ - 为什么以及何时通过指针在 C++ 中传递类类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27929491/