2010-11-14 31 views
16

Tôi nhận được lỗi trình biên dịch này khi gọi số size() của vectơ. Tại sao?lỗi C2228: bên trái '.size' phải có lớp/struct/union

#include <vector> 
#include <iostream> 
#include <fstream> 
#include <sstream> 
#include <string> 
#include <cassert> 


using namespace std; 

class Vertex { 

    float firstValue; 
    float secondValue; 
    float thirdValue; 

    Vertex (float first, float second, float third){ 
      firstValue=first; 
      secondValue=second; 
      thirdValue=third; 
    } 

}; 


int main() 
{ 
    cout<<"This program loads a 3D .off object. \nEnter the name of the file that describes it "<<endl; 
    string inputFileName; 
    getline(cin, inputFileName); 

    ifstream inputFileStream; 

    inputFileStream.open(inputFileName.data()); 
    assert (inputFileStream.is_open()); 

    string actualLine; 

    for(;;){ 

     inputFileStream>>actualLine; 

     istringstream actualLineStream(actualLine); 



     std::vector<float> results(std::istream_iterator<int>(actualLineStream) 
         , std::istream_iterator<int>()); 

     int resultsIndex=0; 
     int resultsSize=results.size(); //WHY?? 

     while (resultsIndex<resultsSize){ 

     cout<<results[resultsIndex]<<endl; 
     } 


     if (inputFileStream.eof()) break; 

    } 


    ofstream outputChannel; 

    while (true){} // to keep on console view 
    return 0; 
} 

Trả lời

48

Tin hay không, dòng này không tuyên bố một thể hiện của std::vector tên results, kêu gọi các nhà xây dựng tham gia một bắt đầu và kết thúc iterator:

std::vector<float> results(std::istream_iterator<int>(actualLineStream), 
    std::istream_iterator<int>()); 

Điều này thực sự tuyên bố một hàm được gọi là results có tham số có tên actualLineStream và một thông số chưa đặt tên khác, cả hai loại std::istream_iterator<int>.

Nói chung trong C++, nếu một cái gì đó trông giống như một hàm, nó sẽ được phân tích cú pháp như một hàm; tiêu chuẩn C++ yêu cầu nó. Điều này thực sự cho khả năng tương thích ngược với C - nhưng điều này phản trực giác đến nỗi nó thậm chí còn có tên riêng của nó: "most vexing parse". Một số trình biên dịch thậm chí sẽ đưa ra cảnh báo nếu nó gặp phải phân tích cú pháp gây tranh cãi nhất.

Nó có liên quan đến thực tế là hai dòng đây không phải là tương đương trong C++:

Foo bar; // Declares an instance of Foo named bar 
Foo bar(); // Declares a function named bar that takes no parameters and returns a Foo 

Để khắc phục nó, bạn có thể thêm dấu ngoặc xung quanh một trong những đối số:

//       +--------- Note extra parentheses!! ---------+ 
//       |           | 
//       V           V 
std::vector<float> results((std::istream_iterator<int>(actualLineStream)), 
    std::istream_iterator<int>()); 

Hoặc chỉ cần khai báo riêng từng trình vòng lặp:

std::istream_iterator<int> resultsBegin(actualLineStream); 
std::istream_iterator<int> resultsEnd; 
std::vector<float> results(resultsBegin, resultsEnd); 
+4

Wow .. Tôi sẽ không bao giờ nghĩ về điều đó. – andandandand

+0

Tôi rất vui vì tôi đã tìm thấy bài đăng này. Hành vi này thật khủng khiếp. –

+0

Vâng, cảm ơn Chúa tôi đã tìm thấy điều này. Tôi đã sẵn sàng để ném máy tính xách tay của tôi ra ngoài cửa sổ. – MikeTheLiar

6

Tôi nghĩ bạn nhấn this bugaboo . Bạn đã quản lý để khai báo results là một hàm mới trả về một số std::vector<float>. Nếu tôi thay đổi dòng khai báo results tới:

std::vector<float> results = std::vector<float>(std::istream_iterator<int>(actualLineStream), std::istream_iterator<int>()); 

tôi có thể biên dịch này (với GCC, tuy nhiên, YMMV)

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