爲了理解對象切片的問題,我認爲我創建了一個可怕的例子,我試圖測試它。但是,這個例子並沒有我想象的那麼糟糕。瞭解對象切片
下面是一個最簡單的工作示例,如果您能幫助我理解爲什麼它仍「正常工作」,我將不勝感激。如果你幫我讓這個例子變得更糟,那會更好。
#include <functional>
#include <iostream>
template <class T> class Base {
protected:
std::function<T()> f; // inherited
public:
Base() : f{[]() { return T{0}; }} {} // initialized
virtual T func1() const { return f(); }
virtual ~Base() = default; // avoid memory leak for children
};
template <class T> class Child : public Base<T> {
private:
T val;
public:
Child() : Child(T{0}) {}
Child(const T &val) : Base<T>{}, val{val} { // initialize Base<T>::f
Base<T>::f = [&]() { return this->val; }; // copy assign Base<T>::f
}
T func1() const override { return T{2} * Base<T>::f(); }
void setval(const T &val) { this->val = val; }
};
template <class T> T indirect(const Base<T> b) { return b.func1(); }
int main(int argc, char *argv[]) {
Base<double> b;
Child<double> c{5};
std::cout << "c.func1() (before): " << c.func1() << '\n'; // as expected
c.setval(10);
std::cout << "c.func1() (after): " << c.func1() << '\n'; // as expected
std::cout << "indirect(b): " << indirect(b) << '\n'; // as expected
std::cout << "indirect(c): " << indirect(c) << '\n'; // not as expected
return 0;
}
輸出,當我編譯代碼如下獲得:
c.func1() (before): 10
c.func1() (after): 20
indirect(b): 0
indirect(c): 10
我希望最後一行拋出一些異常或者乾脆失敗。當c
的基本部分被切片爲indirect
時,在lambda表達式中沒有this->val
被使用(我知道,C++是靜態編譯語言,而不是動態的)。我也嘗試在複製分配Base<T>::f
時通過值捕獲this->val
,但它沒有改變結果。
基本上,我的問題是兩個褶皺。首先,這是未定義的行爲,還是僅僅是一個合法的代碼?其次,如果這是一個合法的代碼,爲什麼行爲不受切片的影響?我的意思是,我可以看到T func1() const
是從Base<T>
部分調用的,但爲什麼捕獲的值不會造成任何麻煩?
最後,我怎樣才能建立一個例子,使內存訪問類型的問題更糟糕的副作用?
預先感謝您的時間。
編輯。我知道已被標記爲重複的其他主題。我已經閱讀了所有帖子,其實我一直試圖在那裏複製the last post。正如我以上問,我試圖得到的行爲
然後關於成員酒吧b中的信息丟失在一個。
我不能完全得到。對我而言,只有部分信息似乎丟失了。基本上,在最後一篇文章中,該人聲稱
來自實例的額外信息已經丟失,並且f現在傾向於未定義的行爲。
在我的例子中,f
似乎也工作得很好。相反,我只是打電話給T Base<T>::func1() const
,這並不奇怪。
「_and f是現在容易未定義behaviour_」「我_IN例如,'F'似乎well._」未定義行爲是不確定的是剛剛工作。未定義行爲的許多可能表現之一是代碼_seeming_正常工作。 –
@AlgirdasPreidžius,上面的行爲也是如此,在我的例子中,undefined?我是否僅僅因爲在這個有限的,最簡單的例子中運氣或緩存了一些變量而簡單地獲取_seemingly_工作代碼?這就是我想要了解的。 –
我不知道,如果你的例子中的代碼產生未定義的行爲。我只是想說明,代碼_seems_正常工作的事實不是**證明它不會顯示未定義的行爲。 –