簡體   English   中英

C ++中的虛擬移動構造函數

[英]Virtual move constructor in C++

只是面對一種情況,不知道該怎么辦...這是我現在擁有的代碼:

class IMyDbAccessor {
 public:
  int getSum();  // quite important for my case that it is not const.
                 // it does some caching. Of course I may use mutable,
                 // but actually it is not that important here.
};

void SomeBusinessLogic(IMyDbAccessor& dbacc) { /* implementation */ }

int main(int argc, char** argv) {
    MyDbAccessor acc(argv);
    SomeBusinessLogic(acc);
}

我不喜歡它,因為它的表現力不足。 我想擁有

void SomeBusinessLogic(IMyDbAccessor&& dbacc) { /* implementation */ }

表明SomeBusinessLogic想要擁有一個傳遞的對象,所以main應該看起來像

int main(int argc, char** argv) {
    MyDbAccessor acc(argv);
    SomeBusinessLogic(std::move(acc));
}

但是,當然這是不可能的……沒有人知道這是什么原因嗎? 對我來說,這是完全合理的。

還是我的SomeBusinessLogic是錯誤的,我不應該讓SomeBusinessLogic負責IMyDbAccessor所有權,所以最好將其作為const IMyDbAccessor&傳遞?

我認為您正在尋找的類型可能是void SomeBusinessLogic(std::unique_ptr<IMyDbAccessor>)嗎?

表示所有權正在轉移,並接受派生對象

我不喜歡它,因為它的表現力不足。

看起來很能表達我的意思。 通過引用傳遞對象意味着該功能可以對調用方提供的現有對象進行操作,而不是對副本進行操作。 不用擔心管理所有權。

我想擁有

 void SomeBusinessLogic(IMyDbAccessor&& dbacc) { /* implementation */ } 

表明SomeBusinessLogic要擁有一個傳遞的對象

那不是右值引用所代表的。 右值引用意味着dbacc將引用由編譯器在實際調用站點處創建的臨時對象,或調用方通過std::move()傳遞的預先存在的對象。 無論哪種方式,都希望在SomeBusinessLogic()退出后不再使用dbacc引用的對象,因此允許SomeBuinessLogic() “竊取” dbacc引用的對象持有的任何內部數據的所有權,而不是進行復制它的。 這與對象本身的所有權無關。 這仍然嚴格取決於調用方。

所以main應該看起來像

 int main(int argc, char** argv) { MyDbAccessor acc(argv); SomeBusinessLogic(std::move(acc)); } 

但是當然不可能...

您正在尋找的是std::unique_ptr

void SomeBusinessLogic(std:::unique_ptr<IMyDbAccessor> dbacc) { /* implementation */ }

int main(int argc, char** argv) {
    std::unique_ptr<IMyDbAccessor> acc(new MyDbAccessor(argv));
    SomeBusinessLogic(std::move(acc));
}

要么:

int main(int argc, char** argv) {
    SomeBusinessLogic(std::make_unique<MyDbAccessor>(argv));
}

一次只能有一個std::unique_ptr持有給定的指針,因為std::unique_ptr釋放了被破壞時指向的內存。 那就是使它“獨特”的原因。 當您看到std::unique_ptr ,您知道所有者是誰。 通過值將std::unique_ptr對象傳遞給函數意味着該對象僅在函數的生存std::unique_ptr存在。

因此,這種方法非常清楚, dbacc本身(而不是調用者)擁有IMyDbAccessor對象的專有所有權,並且將在SomeBusinessLogic()退出時釋放該對象(除非SomeBusinessLogic()決定將std::move() dbacc移至另一個)位於SomeBusinessLogic()之外的std::unique_ptr

還是我的SomeBusinessLogic是錯誤的,我不應該讓SomeBusinessLogic負責IMyDbAccessor所有權,所以最好將其作為const IMyDbAccessor&傳遞?

我會的,是的。 除非有令人信服的理由, SomeBusinessLogic()必須將所有權從調用者手中奪走。

執行SomeBusinessLogic(std :: forward(acc))。

例如:

#include <iostream>
#include <utility>

class IMyDbAccessor {
public:
  virtual int getSum() = 0;

};

class MyDbAccessor : public IMyDbAccessor {
public:
    virtual int getSum() { return 0; }

};

void SomeBusinessLogic(IMyDbAccessor&& dbacc) { std::cout << dbacc.getSum() << std::endl; }

int main(int argc, char** argv) {
    MyDbAccessor acc;
    SomeBusinessLogic(std::forward<MyDbAccessor>(acc));
}

在這里嘗試: http : //cpp.sh/7pbrm

如果您正在尋找一種反饋的方式,“嘿,我將修改此變量!” 在調用位置,我強烈建議使用const指針。

然后您有:

void SomeBusinessLogic(IMyDbAccessor* const dbacc) { /* implementation */ }

int main(int argc, char** argv) {
    MyDbAccessor acc;
    SomeBusinessLogic(&acc);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM