8

Đây là lớp học có phương pháp chưa được xác định. Có vẻ như các trình biên dịch cho phép các cá thể của lớp này được xây dựng, miễn là hàm thành viên không xác định không bao giờ được gọi là:Có phải tất cả các phương pháp chưa được xác định chưa được sử dụng đều được phép không?

struct A { 
    void foo(); 
}; 

int main() { 
    A a;  // <-- Works in both VC2013 and g++ 
    a.foo(); // <-- Error in both VC2013 and g++ 
} 

Đây là một tình huống tương tự, nhưng có liên quan đến kế thừa. Phân lớp Bar mở rộng lớp cơ sở Foo. Foo xác định phương thức g(). Bar tuyên bố phương thức có cùng tên nhưng không xác định phương thức đó:

#include <iostream> 

struct Foo { 
    void g() { std::cout << "g\n"; } 
}; 

struct Bar : Foo { 
    void g(); 
}; 

int main() { 
    Bar b;  // Works in both VC2013 and g++ 
    b.Foo::g(); // Works in both VC2013 and g++ 
    b.g();  // Error in both VC2013 and g++ 
} 

Đây là một biến thể ở trên. Sự khác biệt duy nhất ở đây là g()virtual cho cả FooBar:

#include <iostream> 

struct Foo { 
    virtual void g() { std::cout << "g\n"; } 
}; 

struct Bar : Foo { 
    virtual void g(); 
}; 

int main() { 
    Bar b;  // Works in g++. But not in VC2013, which gives 
       // 'fatal error LNK1120: 1 unresolved externals' 

    b.Foo::g(); // Works in g++, but VC2013 already failed on b's construction 
    b.g();  // Error in g++, but VC2013 already failed on b's construction 
} 

Xem các ý kiến ​​mã cho độ tương phản của hành vi khác nhau giữa VC2013 và g ++.

  1. Trình biên dịch nào là chính xác, nếu có?
  2. Tại sao trình biên dịch VC2013 có một số khiếu nại khác nhau trong phiên bản với từ khóa virtual so với từ khóa trong phiên bản của từ khóa mà không có từ khóa virtual?
  3. Các phương pháp chưa được xác định chưa sử dụng luôn được phép không? Nếu không, tất cả các trường hợp mà chúng không được phép là ?
  4. Tuyên bố của Barg() được tính là ghi đè ngay cả khi Bar không cung cấp định nghĩa?
+0

Vtable được tham chiếu trong hàm tạo và cần địa chỉ của các hàm ảo, vì vậy lỗi VC2013 có vẻ hợp lý. – BartoszKP

Trả lời

8

Trình biên dịch nào là đúng, nếu có?

Cả hai đều đúng. Mã của bạn sai, không yêu cầu chẩn đoán. [class.virtual]/11

Hàm ảo được khai báo trong lớp phải được xác định hoặc khai báo thuần túy (10.4) trong lớp đó hoặc cả hai; nhưng không cần chẩn đoán (3.2).

[intro.compliance]/2:

Nếu một chương trình chứa một vi phạm một quy tắc mà không có chẩn đoán là yêu cầu, này nơi tiêu chuẩn quốc tế không có yêu cầu về triển khai liên quan đến điều đó với chương trình.

Hãy xem cài đặt tối ưu hóa của bạn cho GCC, chúng có thể ảnh hưởng đến hành vi.


Phương pháp chưa xác định chưa được sử dụng luôn được phép?

Chức năng thành viên phải được xác định khi và chỉ khi nó được sử dụng không đúng. [basic.def.odr]/3:

Mỗi chương trình phải chứa chính xác một định nghĩa của mọi hàm hoặc biến không nội tuyến hoặc biến được sử dụng không đúng trong chương trình đó; không cần chẩn đoán .

Bây giờ xem xét [basic.def.odr]/2:

Một biểu thức được có khả năng đánh giá trừ khi nó là một toán hạng unevaluated (khoản 5) hoặc một subexpression đó.
[…]
Chức năng thành viên ảo không được sử dụng nếu nó không thuần khiết.
Hàm không quá tải có tên xuất hiện dưới dạng biểu thức có khả năng được đánh giá hoặc thành viên của tập hợp các hàm ứng cử viên, nếu được chọn theo độ phân giải quá tải khi được tham chiếu từ biểu thức có khả năng được đánh giá. chức năng ảo thuần túy và tên của nó không đủ điều kiện.

Bạn vẫn được phép sử dụng các chức năng thành viên không được xác định không phải ảo bên trong decltype hoặc sizeof. Nhưng các hàm ảo không thuần khiết được sử dụng odr đơn giản chỉ vì chúng không thuần khiết.


tuyên bố g Liệu Bar() được tính là trọng ngay cả khi Bar không cung cấp một định nghĩa?

Có.

+0

Về, 'Cả hai đều đúng', bạn có nghĩa là không sao cho g ++ xây dựng thành công 'b' (lớp nào có phương thức ảo) trong khi VC2013 không thể, bởi vì nó là hành vi không xác định? – CodeBricks

+1

@CodeBricks Khá giống với hành vi không xác định. Kiểm tra [câu trả lời này] (http://stackoverflow.com/questions/22180312/difference-between-undefined-behavior-and-ill-formed-no-diagnostic-message-requ). – Columbo

+0

Điều đó có nghĩa là một chức năng ảo không thuần túy không cần phải được gọi là sử dụng odr? – CodeBricks

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