Gần đây tôi gặp phải một vấn đề mà bằng cách nào đó (nhưng chỉ bằng cách nào đó) có ý nghĩa với tôi. Nó được dựa trên việc giải thích việc xây dựng tạm thời như là khai báo đối số hàm tạo đơn (!). Vui lòng xem ví dụ tối thiểu bên dưới.Xây dựng tạm thời trong cuộc gọi chức năng được hiểu là khai báo
#include <iostream>
class Foo0{
public:
Foo0(int a){};
void doStuff() {std::cout<<"maap"<<std::endl;};
};
class Foo1{
public:
Foo1(int a){};
void doStuff() {std::cout<<"maap"<<std::endl;};
};
class Foo2{
public:
Foo2(int a){};
void doStuff() {std::cout<<"maap"<<std::endl;};
};
class Bar{
public:
Bar(Foo0 foo0, Foo1 foo1, Foo2 foo2){};
};
int main() {
int x = 1;
Bar bar0(Foo0(x), Foo1(x), Foo2(x)); // Does not work: conflicting declaration ‘Foo1 x’ previous declaration as ‘Foo0 x’; conflicting declaration ‘Foo2 x’ previous declaration as ‘Foo0 x’
Bar bar1(Foo0{x}, Foo1(x), Foo2(x)); // Works WTF
Bar bar2(Foo0(x), Foo1{x}, Foo2(x)); // Works WTF
Bar bar3(Foo0(x), Foo1(x), Foo2{x}); // Does not work: conflicting declaration ‘Foo1 x’ previous declaration as ‘Foo0 x’
Bar bar4(Foo0{x}, Foo1{x}, Foo2{x}); // Works totally makes sens to me
x.doStuff(); //Dose not work. This makes sens to me. But in the context its curious though.
}
Tôi đã đọc cuốn sách biểu như:
Foo(a);
đang giải thích (nếu có một nhà xây dựng tiêu chuẩn) như lời tuyên bố của một. Điều này làm cho tinh thần và nó là hoàn toàn tốt, vì bạn chỉ có thể sử dụng {} -brackets để làm cho việc xây dựng rõ ràng. Nhưng những gì tôi không hiểu là:
Tại sao có vấn đề với việc xây dựng bar0? Tất cả
Foo
s không có hàm tạo tiêu chuẩn. Vì vậy, nó không có ý nghĩa để giải thích một cái gì đó nhưFoo0(x)
như tuyên bố củax
.Tại sao việc xây dựng các công trình
bar1
vàbar2
hoạt động? Rõ ràng với tôi rằng việc xây dựngbar4
hoạt động, vì tôi sử dụng {} -brackets cho tất cả các tạm thờiFoo
s, do đó tôi rõ ràng về những gì tôi muốn.Nếu chỉ cần sử dụng {} -brackets chỉ với một trong số
Foo
s để giải quyết vấn đề ... tại sao việc xây dựngbar3
không thành công?Ngoài ra, x được khai báo trước khi bất kỳ Thanh nào được tạo. Tại sao trình biên dịch không phàn nàn về điều đó?
Câu hỏi cuối cùng liên quan đến dòng mã mẫu cuối cùng của tôi. Câu chuyện dài ngắn: Trình biên dịch nghĩ rằng tôi muốn anh ấy làm gì và tôi bỏ lỡ sự xuất hiện của bóng tối ở đâu?
PS: Nếu nó quan tâm - tôi sử dụng gcc-4.9.2.
PPS: Tôi đã thử cùng với hàm tạo của bar
lấy ba đối số Foo0
s làm đối số. Cùng câu chuyện ở đây. Nhưng lỗi này không nói gì về việc khai báo mâu thuẫn nhưng về định nghĩa lại x
.
Để bạn biết, 'bar0' là khai báo hàm có ba' Foo 'và trả về một' Foo', nó không phải là một đối tượng 'Foo'. Ngoài ra, thực tế là việc khai báo 'bar3' không hoạt động là một lỗi trong bất kỳ trình biên dịch nào bạn đang sử dụng. Dòng đó sẽ hoạt động như trong [clang] (http://coliru.stacked-crooked.com/a/d5f8305eff385830). – 0x499602D2
@ 0x499602D2 đã báo lỗi cho tôi bằng g ++ 4.8.1 –
Chỉ cần chính xác: 'bar0' là khai báo hàm có ba' Foo 'và trả về' Thanh '. – sedriel