2012-01-02 34 views
5

Tôi có một đoạn mã như thế này:chức năng Nội đối phó với biến từ phạm vi

std::list<boost::shared_ptr<Point> > left, right; 
// ... fill lists ... 

// now, calculate the angle between (right[0], right[1]) and (right[0], left[0]) 
double alpha = angle(*(right.begin()->get()), *(((++right.begin()))->get()), *(left.begin()->get())); 

std::cout << alpha * 180/M_PI << std::endl; 

if(alpha < 0){ 
    // do something with the lists, like reversing them. Especially the beginning and end of the lists may change in some way, but "left" and "right" are not reassigned. 
} 

// calculate the new alpha 
alpha = angle(*(right.begin()->get()), *(((++right.begin()))->get()), *(left.begin()->get())); 

Ngoài các iterator ma thuật tăng mà có thể không được quá obvoius đây mà không có ý kiến, tôi muốn xác định một hàm double alpha() để giảm trùng lặp. Nhưng vì việc sử dụng hàm này rất cụ thể, tôi muốn biến nó thành một hàm cục bộ. Lý tưởng nhất là:

int a, b; 
int sum(){ return a + b; } 
a = 5; b = 6; 
int s = sum(); // s = 11 
a = 3; 
s = sum(); // s = 9 now 

Trong các ngôn ngữ như Python, điều này hoàn toàn ổn, nhưng cách thực hiện điều này trong C++?

EDIT:

Đây là những gì tôi đã kết thúc với, đặc biệt nhờ vào @wilx và -std=c++0x biên dịch cờ:

auto alpha = [&right, &left]() { 

    // not 100% correct due to my usage of boost::shared_ptr, but to get the idea 

    Point r_first = *(right.begin()); 
    Point l_first = *(left.begin()); 
    Point r_second = *(++right.begin()); 

    return angle(r_first, r_second, l_first); 
}; 


if(alpha() < 0) // fix it 

double new_alpha = alpha(); 
+4

C++ không có chức năng lồng nhau. Có một phần mở rộng trong GCC cho phép nó mặc dù, và trong tiêu chuẩn C++ 11 có [hàm lambda] (http://en.wikipedia.org/wiki/C%2B%2B11#Lambda_functions_and_expressions) có thể được sử dụng thay thế. –

+1

Có lý do nào để sử dụng 'danh sách' thay vì' vectơ' không? Bạn sẽ không cần gia số lặp của hacky nếu bạn sử dụng 'vector'. Xem xét cũng chỉ sử dụng 'cặp' nếu danh sách luôn có hai phần tử. –

Trả lời

1

Trong trường hợp này, tôi khuyên bạn nên sử dụng quá tải như angle2(std::list<Point> const &, etc.). Hai đối số đơn giản là tốt hơn so với những gì bạn có bây giờ.

Với C++ 11, bạn có thể sử dụng lambdas bắt đối số của chúng bằng cách tham chiếu.

Nếu bạn không thể sử dụng C++ 11 và bạn cảm thấy phiêu lưu, hãy thử Boost.Phoenix (một phần của Boost.Spirit).

+0

'auto alpha = [& right, & left]() {return angle (...); }; std :: cout << alpha() * 180/M_PI << std :: endl; '- dường như làm trò lừa. –

0

C++, theo như tôi biết, không cho phép điều này. Bạn có thể giới hạn ô nhiễm không gian tên được tạo ra bằng cách gắn thêm bộ định danh tĩnh vào đầu chữ ký hàm cho alpha, nhưng bạn vẫn phải định nghĩa nó một cách riêng biệt.

Điều này sẽ làm cho tên chỉ được sử dụng trong tệp nguồn đó. Bạn cũng có thể xác định một macro trong hàm, cẩn thận để xác định lại nó nếu bạn không muốn tính tiền xử lý kỳ lạ sau này.

int a, b; 
#define SUM() (a+b) 
int s=sum() 
#undef SUM 
2

C++ không hỗ trợ chức năng lồng nhau, nhưng một workaround có thể được thực hiện với các lớp chức năng đặt phạm vi:

void scopeFnc() 
{ 
    struct Inner 
    { 
    static int nestedFnc() { return 5; } 
    }; 

    int a = Inner::nestedFnc(); 
} 
+0

Tôi hiểu ý của bạn, nhưng 'nestedFnc' không thể truy cập các biến được khai báo trong' scopeFnc', ít nhất GCC phàn nàn về điều đó. Nhưng ít nhất giải pháp này giúp giảm thiểu sự ô nhiễm không gian tên; Tôi có thể làm cho nó bằng cách sử dụng hai danh sách như là đối số. –

+0

@ wal-o-mat: đủ công bằng, nếu bạn thực sự cần nó, bạn có thể khai báo các biến cần thiết bên trong Inner, nhưng tôi thừa nhận rằng điều đó sẽ không làm cho chức năng của bạn sạch hơn. – stefaanv

Các vấn đề liên quan