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

考虑下面的代码:

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

class Derived: public Abstract{
public:
    void printStuff(){
        printf("Stuffn");
    }
};

现在,我们假设我想创建一个使用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();
}

现在,我明白了第二个在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>())
{
}

实际上有五种不同的可能性将对象传递给函数:

//Function declarations
void passByValue(Derived o);    //Not possible with an abstract class.
void passByReference(Abstract& o);
void passByConstReference(const Abstract& o);
void passByPointer(Abstract* o);
void passByConstPointer(const Abstract* o);

//Function calls
Derived o;
passByValue(o);
passByReference(o);      //May change o!
passByConstReference(o);
passByPointer(&o);       //May change o.
passByConstPointer(&o);

因为passByReference(o)调用中不可见,调用可能会修改变量o ,所以我从不使用传递引用。 我总是使用pass-by-const-reference或pass-by-pointer。

然而,今天许多C ++程序员一般都憎恶指针的使用,因为它们不能很好地使用像std::unique_ptr<>std::shared_ptr<>这样的智能指针。 如果您使用这些智能指针来管理对象,则必须始终通过智能指针而不是裸指针/引用(通常通过const-reference):

void passBySmartPointer(const std::shared_ptr<Abstract>& o);
void passConstBySmartPointer(const std::shared_ptr<const Abstract>& o);

采用这种方法,您永远不会在代码中看到裸指针...

(需要传递智能指针的原因是智能指针链不能被破坏:如果将智能指针转换为裸指针,然后返回智能指针,则第二个智能指针不知道第一,你会得到麻烦,还有其他方法可以避免这种情况,但这超出了本答案的范围。)

链接地址: http://www.djcxy.com/p/20731.html

上一篇: Why and when to pass class types in C++ by pointer?

下一篇: Passing by reference options in C++