2010-02-16 24 views
7

Observation: the codes pasted below were tested only with GCC 4.4.1, and I'm only interested in them working with GCC.Object xây dựng/Forward khai báo hàm mơ hồ

Xin chào,

Đó là không chỉ một vài lần mà tôi vấp vào một tuyên bố xây dựng đối tượng mà tôi không hiểu, và nó là chỉ ngày hôm nay tôi nhận thấy sự mơ hồ nào được giới thiệu bởi nó. Tôi sẽ giải thích làm thế nào để tái sản xuất nó và muốn biết nếu có một cách để sửa chữa nó (C++ 0x cho phép). Nó đi từ đây.

Giả sử có một lớp mà hàm tạo chỉ nhận một đối số và loại đối số của một đối số này là một lớp khác với hàm tạo mặc định. Ví dụ:

struct ArgType {}; 

class Class 
{ 
public: 
    Class(ArgType arg); 
}; 

Nếu tôi cố gắng xây dựng một đối tượng kiểu Class trên stack, tôi nhận được một sự mơ hồ:

Class c(ArgType()); // is this an object construction or a forward declaration 
        // of a function "c" returning `Class` and taking a pointer 
        // to a function returning `ArgType` and taking no arguments 
        // as argument? (oh yeh, loli haets awkward syntax in teh 
        // saucecode) 

tôi nói nó là một xây dựng đối tượng, nhưng trình biên dịch khẳng định đó là một lời tuyên bố về phía trước bên trong thân hàm. Đối với những người vẫn không hiểu, đây là ví dụ hoàn toàn làm việc:

#include <iostream> 

struct ArgType {}; 
struct Class {}; 

ArgType func() 
{ 
    std::cout << "func()\n"; 
    return ArgType(); 
} 

int main() 
{ 
    Class c(ArgType()); 

    c(func); // prints "func()\n" 
} 

Class c(ArgType funcPtr()) // Class c(ArgType (*funcPtr)()) also works 
{ 
    funcPtr(); 
    return Class(); 
} 

Vì vậy, đủ ví dụ. Bất cứ ai cũng có thể giúp tôi vượt qua điều này mà không làm bất cứ điều gì quá chống thành ngữ (tôi là một nhà phát triển thư viện và những người như thư viện thành ngữ)?

- chỉnh sửa

Không sao. Đây là bản dupe của Most vexing parse: why doesn't A a(()); work?.

Xin cảm ơn, sbi.

+0

Mã của bạn biên dịch cho tôi với g ++ - đó chút nào bạn nghĩ rằng không nên làm việc? –

+0

Nó không phải là vấn đề làm việc hay không hoạt động. Vấn đề là tôi chỉ muốn xây dựng một đối tượng kiểu 'Class' và truyền hàm tạo của nó một đối tượng kiểu' ArgType' được xây dựng bên trong .. Nhưng nó nhận ra như một khai báo chuyển tiếp. Tôi sẽ thêm mã mà tôi muốn làm việc nhưng không thể, chỉ một giây. –

+0

Quên đi, Neil. Nhìn vào câu trả lời của sbi, đó chính là vấn đề của tôi. –

Trả lời

5

Điều này được gọi là "phân tích cú pháp khó chịu nhất" của C++. Xem here, herehere.

1

Dựa vào "C++ 0x cho phép", câu trả lời đúng là (có thể) để thay đổi định nghĩa để:

Class c(ArgType {}); 

đơn giản, thẳng thắn và đặt gánh nặng hoàn toàn vào người sử dụng của thư viện, không phải tác giả!

Chỉnh sửa: Có, ctor được gọi - C++ 0x thêm Danh sách-Khởi tạo như một cách rõ ràng để phân định danh sách khởi tạo. Nó không thể được phân tích sai như trong mẫu của bạn, nhưng nếu không thì ý nghĩa là gần như giống như khi bạn sử dụng dấu ngoặc đơn. Xem N3000, dấu đầu dòng thứ ba theo §8.5.4/3. Bạn có thể viết một ctor để nhận một danh sách khởi tạo như một đối số duy nhất, hoặc các mục trong danh sách khởi tạo có thể được kết hợp với các đối số ctor riêng lẻ.

+0

Đợi .. nhưng điều đó sẽ không gọi cho nhà xây dựng, phải không? –

+1

Thực ra điều đó dường như không được chấp nhận đối với GCC 4.4.1. Tuy nhiên, các kết hợp khác: 'Class c {ArgType {}};' hoặc 'Class c {ArgType()};' Và thêm một phiên bản không phải C++ 0x để gọi hàm tạo: 'Class c ((ArgType())); ' – UncleBens

1

Hãy đơn giản hóa một chút.

int f1(); 

Đó là gì? Trình biên dịch (và tôi) nói đó là một khai báo chuyển tiếp cho một hàm trả về một số nguyên.

Làm thế nào về điều này?

int f2(double); 

Trình biên dịch (và tôi) nói đó là tuyên bố chuyển tiếp cho một hàm lấy tham số kép và trả về int.

Vì vậy, bạn đã thử này:

ClassType c = ClassType(ArgType()); 

Kiểm tra các C++ faq Lite trên constructors cho explanations và các ví dụ