2016-10-03 91 views
2

考慮以下情況最佳實踐從一個const-方法

class A 
{ 
public: 
    void someFunc() const 
    { 
     b->nonConstFunction(); //this is a non const function in the class B 
    } 

private: 
    B* b; 
}; 

在恆定函數someFunc()訪問部件的指針的一個非const方法時,我可以調用b任何非恆定方法它將編譯。所以函數someFunc()在某種程度上不是一個真正的const函數。但是,所有最佳實踐都表示,應該在任何地方放置const。這個建議是否也適用於這裏? 可能會聲明函數void someFunc()非常量更爲誠實然後void someFunc() const。或者可能有更一般的建議來處理這類事情?

+1

這實際上取決於'A類'代表什麼。這裏沒有一個適合所有人的尺寸。 – juanchopanza

+0

看看['mutable'](http://en.cppreference.com/w/cpp/language/cv)=>對於這樣的情況,它是完美的:定義一個可以在const環境中修改的變量因爲無論類實例如何,它都不在乎(恕我直言,一個很好的例子是互斥體=>互斥體必須在const env中修改) – Garf365

+4

如果您有權訪問副本,您可能需要閱讀Effective C++中的項目邏輯與逐位常數;這正是您目前的困惑。 [這個問題](http://stackoverflow.com/questions/3830367/difference-between-logical-and-physical-const-ness#3830484)對此有一些討論。 – TartanLlama

回答

4

在某種程度上不是一個真正的const函數

得好:

你可以通過創建一個指針包裝,傳遞給所包含指針的常量性,像這樣解決這個問題這取決於你想表達什麼。

  1. 如果A的狀態在邏輯上取決於b的狀態(這是暗示我從你的問題得到)

    • 簡單的解決方法是給AB類型的成員,而不是使用指針或引用。然後,你必須在你的常量方法const B,這表示您的要求直接

    • 下一個最簡單的是剛剛宣佈該成員爲const B *b;擺在首位 - 這顯然不工作,如果你還需要非const方法的A調用b上的非常量方法。

    • 如果你需要間接,另一種可能是使用智能指針類(我不知道如果有合適的一個已經存在)與運算符重載像

      B* operator->(); 
      const B* operator->() const; 
      

      這樣會給你保證要

  2. 如果A的狀態不邏輯上依賴於b的。

    在這種情況下,您沒有問題:在const方法中變異b方法沒有問題,因爲A的邏輯狀態不會更改。這可能通常是你有一個指向例如。一個記錄器,否則會需要大量的可變成員。

1

如果A不是「擁有」B,它是常量。現代C++表示通過使b成爲unique_ptr是A是擁有者,如果是鏈接,則是普通指針。

1

這似乎是C++觀點B爲不可的A一部分但A連接B。如B不是constA可以調用它的非常量方法。但是因爲A常數您不能讓A指向一個不同的B。如果您使B成爲成員,則您不能再調用其非常量方法,因爲它現在是A的一部分。

我想用一個std::unique_ptr可以解決這個問題,但顯然std::unique_ptr常量箭頭操作符->返回非const指針。

template<typename T> 
class const_correct_ptr 
{ 
public: 
    const_correct_ptr(std::unique_ptr<T>): p(std::move(p)) {} 

    // pass constness onto target 
    T* operator->() { return p.get(); } 
    T const* operator->() const { return p.get(); } 

private: 
    std::unique_ptr<T> p; 
}; 

class B 
{ 
public: 
    void nonConstFunction() {} 
}; 

class A 
{ 
public: 
    A(): b(std::make_unique<B>()) {} 

    void someFunc() const 
    { 
     b->nonConstFunction(); // compile time error! 
    } 

private: 
    const_correct_ptr<B> b; 
};