[英]Can I create anonymous classes in C++ and capture the outside variables like in Java?
在Java中,當我需要一個回調函數時,我必須實現一個匿名類。 在匿名類中,如果它們是final
,我可以訪問外部變量。
現在我在C ++中做同樣的事情。 我理解C ++ lambda工作得更好但有時候我需要傳入許多帶有匿名類的函數,我只需要傳入一個實例。
我嘗試了以下示例。 它適用於GCC 4.3.4。
class IA {
public:
virtual int f(int x) = 0;
};
int main() {
class : public IA {
int f(int x) { return x + 1; }
} a;
doFancyWork(&a);
return 0;
}
有可能像這樣捕獲外部變量嗎?
int main() {
int y = 100; // mark y as final if possible
class : public IA {
int f(int x) { return x + y; }
} a;
return 0;
}
更新:
第二個例子不會編譯。 錯誤在這里,
prog.cpp: In member function ‘virtual int main()::<anonymous class>::f(int)’:
prog.cpp:9: error: use of ‘auto’ variable from containing function
prog.cpp:7: error: ‘int y’ declared here
prog.cpp: In function ‘int main()’:
prog.cpp:7: warning: unused variable ‘y’
更新:
我剛剛意識到這樣做的一些問題:
我想我必須離開匿名課程。
無法自動捕獲這些變量,但您可以使用其他方法。 如果您想通過引用捕獲:
int main() {
int y = 100; // mark y as final if possible
class IB : public IA {
public:
IB(int& y) : _y(y) {}
int f(int x) { return x + _y; }
private:
int& _y;
} a (y);
return 0;
}
如果要按值捕獲,只需將int&
更改為int
。
無論如何,你可以考慮使用lambdas元組作為“多回調”對象,如果這是困擾你的個別lambdas。 您仍然可以將所有內容打包在一個對象中,並且可以免費進行捕獲。
舉個例子:
auto callbacks = make_tuple(
[] (int x) { cout << x << endl; },
[&] () { cout << y << endl; }, // y is captured by reference
[=] (int x) { cout << x + y << endl; }, // y is captured by value
// other lambdas here, if you want...
);
您可以手動捕獲變量(類似於lambda捕獲在幕后執行的操作):
int main() {
int y = 100;
struct {
int& y;
int operator()(int x) { return x + y; }
} anon = { y };
}
然后你可以像這樣使用它:
#include <iostream>
...
std::cout << anon(10) << std::endl;
按預期打印110。 不幸的是,您不能使用此方法從另一個繼承匿名類型,因為初始化列表可構造類型不能從其他類型繼承。 如果繼承是至關重要的,那么你應該使用Andy Prowl概述的構造函數方法 。
C ++ lambda可以捕獲“外部”變量。 [編輯:當我第一次看到這個問題時,我不知何故錯過了他提到他知道lambdas的地方。 無論好壞,C ++沒有任何其他真正類似於匿名類的東西]。
例如:
#include <iostream>
int main(){
int y = 100;
auto lambda = [=](int x) { return x + y; };
std::cout << lambda(2);
}
...打印102
作為其輸出。
請注意,盡管它看起來有點像函數,但C ++ lambda確實會導致創建一個類。 我想我應該補充一點:該類在技術上並不是匿名的,但它有一些從未直接可見的未指定名稱。
編輯:我仍然有點不知道不使用lambdas的理由。 是否意圖使用包含許多成員函數的一個類? 如果是這樣,則不清楚您計划如何指定在哪個時間/為何目的調用哪個成員函數。 我的直接反應是,這聽起來很可疑,好像你試圖扭曲語言來支持有問題的設計。
限制訪問外部變量的類的匿名性不是。 在問題中,y不可訪問,因為該類是在函數內本地定義的。
對本地定義的類有一些限制。 首先,它們只能訪問靜態的局部變量,但可以訪問該函數范圍內可用的任何其他變量。 此外,本地類不能擁有靜態數據成員。
對於匿名類,您不能擁有構造函數或析構函數。 必須在類定義中聲明所有成員函數。 它不能有靜態靜態成員,這包括通常可以在類定義中實例化的const靜態整數成員。 也不允許繼承。
匿名類是C ++的一個不起眼的角落,幾乎沒有實際價值。 Lambda函數和其他技術更加靈活。 但誰知道,也許在某些情況下它可以幫助提高代碼的可讀性。
如果你的IA
類真的只有一個你需要覆蓋的虛方法(而真正的復雜性是其他非虛方法),但是你不想捕獲這個方法需要的局部變量,那么:
int main() {
int y = 100;
auto f = [=](int x){return x+y;};
typedef decltype(f) F;
struct IB : IA {
F _f;
IB(F _f): _f(_f) {}
int f(int x) { return _f(x); }
} a(f);
doFancyWork(&a);
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.