2013-03-20 44 views
8

Tôi đang làm việc trên một đơn vị đăng nhập/truy tìm (và vui lòng không trỏ đến những cái hiện có, điều này là dành cho trải nghiệm nhiều như kết quả).Các đối tượng ẩn danh trên ngăn xếp, trong C++?

Để nhận được dấu vết ngăn xếp cuộc gọi theo thời gian chạy, ý tưởng là tạo một hàm đầu tiên của hàm TraceObject một hàm được nhập, mang thông tin của lớp và hàm hiện tại. Hơi giống như:

TraceObject to("MyClass", "myClassFunction"); 

Các constructor của TraceObject đẩy this trên một chồng mỗi chủ đề, các destructor bật nó một lần nữa. Ngăn xếp do đó có thể được truy vấn cho ngăn xếp cuộc gọi.

Tôi đã làm việc này để thỏa mãn. Tuy nhiên, có một mớ nhỏ: Đối tượng to. Theo thiết kế, không bao giờ được gọi bằng tên đó. Do đó, nó không cần phải một tên, ít nhất là một tên có thể va chạm với bất kỳ số nhận dạng nào được khách hàng sử dụng (hoặc, trong trường hợp tiền tố _, việc triển khai).

tl; dr

Có thể tạo ra một, đối tượng nặc danh phi tạm thời trên stack (tức là một trong đó sẽ sống cho đến khi trở về chức năng, nhưng không có một định danh), và nếu có, làm thế nào nó sẽ được thực hiện?

+3

Tôi không nghĩ rằng đó là đúng có thể, nhưng với một vĩ mô và một cái tên vô danh, bạn có thể đạt được như vậy. Có một lý do hợp lý tại sao bạn cần nó không tên hoặc nó là một điều "không thực sự cần thiết" của nó. –

+0

@KarthikT: Vâng, một macro trình bao bọc là ý tưởng chung. Tôi chỉ tự hỏi liệu tôi có thể làm được với "tối nghĩa" và đạt được "vô hình" hay không. – DevSolar

+0

@Karthik T chính xác, đó cũng là cách tăng nhật ký hiện nó vì vậy tôi đoán là: không có cách nào khác – stijn

Trả lời

5

số

Có đối tượng ẩn danh trong C++, là tạm thời mà là kết quả của biểu thức, tuy nhiên họ chỉ sống trong bối cảnh của bản tuyên bố họ đang ở.

Nếu bạn thực sự cố gắng khai báo một đối tượng ẩn danh, bạn sẽ nhầm lẫn trình phân tích cú pháp và nó sẽ nghĩ bạn đang khai báo ... một hàm!


Nhưng sau đó, có cần thiết không?

Nếu bạn chấp nhận sử dụng macro để thực sự khai báo TraceObject, thì việc sử dụng macro cho từng dấu vết là đơn giản; và do đó cung cấp lớp và chức năng ở đó. Sử dụng __func__ hoặc tương đương, bạn có thể trích xuất tên lớp và tên hàm (bit phân tách chuỗi bắt buộc, tùy thuộc vào trình biên dịch) và làm việc từ đó.

Và tất nhiên, bạn sẽ sử dụng macro cho mỗi lần theo dõi, vì bạn có thể muốn tên tệp và số dòng!

+0

bạn có thể kéo dài thời gian sống của đối tượng tạm thời với tham chiếu const, nhưng tham chiếu const là một tên khác của đối tượng tạm thời: const T & r = T(); – AnatolyS

+0

@AnatolyS: tham chiếu const hoặc tham chiếu rvalue (trong C++ 11), nhưng có, như bạn đã lưu ý, nó sẽ giới thiệu một số nhận dạng. –

+0

Tôi không thích cách thức '__func__' như được thực hiện. Nhưng bạn nhận được dấu kiểm để trả lời câu hỏi, cho dù các đối tượng ẩn danh có thể ("Không"). ;-) – DevSolar

3

Như tôi đã nói trong nhận xét của mình, không thể sử dụng các biến ẩn danh giới hạn phạm vi.

#define BEGIN_LOG TraceObject abcdefghij("", __func__); 

void Function(){ 
    BEGIN_LOG; 

    //bla bla 

} 

Điều này nên làm điều đó, miễn là có macro trình biên dịch để lấy tên Lớp.

Chỉnh sửa: Không may mắn với một cách dễ dàng để có được tên lớp, bạn có thể phải làm một cái gì đó giống như những gì được đề xuất tại Class name macro. Hoặc chỉ cần thực hiện với __FILE__.

Chỉnh sửa: Bạn có thể muốn thử __func____FUNCTION__ để xem một trong hai hoặc cả hai hoạt động như bạn muốn. Không có tiêu chuẩn C++ nào được chỉ định.

+0

AFAIK, '__func__' không nằm trong tiêu chuẩn C++, chỉ C. Hoặc có thay đổi này với C++ 11? – DevSolar

+0

@DevSolar không phải là __FUNCTION__ tôi tin? Bất kỳ ý tưởng nào được hỗ trợ tốt hơn? –

1

Một số dòng số thứ:

#define XPASTE(arg1, arg2) PASTEX(arg1, arg2) 
#define PASTEX(arg1, arg2) arg1 ## arg2 
#define TRACELOG() \ 
      TraceObject XPASTE(trace_object, __LINE__) 
+0

Không có nhiều obfuscation được chiến thắng bằng cách thêm '__LINE__', nhưng ít nhất bạn tránh" shadowing "cảnh báo nếu một thứ hai' TraceObject' được tạo ra. .. – DevSolar

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