为什么以及何时通过指针传递C++中的类类型?

akr*_*ki1 5 c++ oop pointers class

请考虑以下代码:

class Abstract{
public:
    virtual void printStuff()=0;
};

class Derived: public Abstract{
public:
    void printStuff(){
        printf("Stuff\n");
    }
};
Run Code Online (Sandbox Code Playgroud)

现在,假设我想创建一个使用Abstract类的printStuff方法的函数.在我了解到C++中只有一种方法可行之前,我认为有两种方法:指针不太明显,而且更明显,类似于你对int,chars等的期望:

void ptr_function(Abstract* abs){ //non-obvious
    abs->printStuff();
}

void non_ptr_function(Abstract abs){ //obvious, analogous to, say, pow(a,b)
    abs.printStuff();
}
Run Code Online (Sandbox Code Playgroud)

现在,我明白第二个是在C++中被禁止的.但是,我并不真正理解这种设计的根本原因.除了指针与作为参数传递的actal对象之外,上述函数看起来不一样吗?

作为一个后续问题:构建必须"包含"其他抽象类的类作为其中一个字段的首选方法是什么?如果这个问题的答案也是:"指针",那么我是否遗漏了某些东西,或者我是否必须自己跟踪这些物体的时间(即手动删除它们)?对于非抽象类,这不是问题,就好像我不使用指针一样,每当该对象超出范围时,它就会被自动删除(析构函数被调用等等).但是,如果我必须使用指针,看起来微管理会占用大量不必要的时间和代码.

有没有更好的方法来解决这个问题?

mbg*_*gda 12

您无法按值传递抽象类,因为它无法实例化.在大多数情况下,按值传递是错误的事情(或者至少是非最优的).您正在寻找的是通过参考传递:

void ref_function(Abstract & abs)
{
    abs.printStuff();
}
Run Code Online (Sandbox Code Playgroud)

当您通过引用传递时,对abs内部所做的任何修改ref_function都将应用于函数外部的同一实例.理想情况下,在您的测试用例中,您希望传递对象,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>())
{
}
Run Code Online (Sandbox Code Playgroud)

  • 即使您可以按值传递非抽象基类,也要意识到您将获得实际对象的**切片副本**.但是,这里的说法太强烈了.对于具有值行为的对象,例如`int`和`std :: complex <double>`,传递值是正确的.毕竟,每5个都有5个值. (4认同)
  • 并且,在这种情况下,`const`引用 (2认同)