2015-11-12 21 views
6

Tôi có này tình hình (giản thể):độ phân giải phạm vi ngắn hơn cho các lớp lồng nhau tin

class Tree { 
    class Iterator { 
     class Stack { 
      // ... 
     } 
    public: 
     // ... 
    } 
public: 
    //... 
} 

Tôi không muốn lộn xộn định nghĩa của lớp học và tôi quyết định viết chỉ khai báo phương thức trong lớp mình. Sau đó (waaay xuống dưới) khi tôi muốn xác định, giả sử, hãy sao chép toán tử gán như sau:

Tree::Iterator::Stack& Tree::Iterator::Stack::operator = (const Stack& p_stack) { 
// ... 
} 

Tôi phải giải quyết các độ phân giải phạm vi khó chịu này. Tôi tự hỏi nếu có cách để rút ngắn chúng, bởi vì usingtypedef, như tôi biết, không cung cấp cho tôi bất cứ điều gì.

EDIT: Vì đây không phải là CodeReview, và @Yulian yêu cầu làm rõ, đây là phiên bản ngắn:

Tôi đang làm cho một thực hiện Đỏ-Đen Tree lặp đi lặp lại. Được đề cập đến class Iterator là dành cho việc di chuyển sau đơn đặt hàng (do đó, theo thứ tự cụ thể là) và class Stack là lớp tiện ích của nó. Trong chương trình ngắn này, chỉ class Tree sử dụng số Iterator và chỉ Iterator sử dụng Stack. Sau khi lời nhắc của @ Yulian, tôi nhớ lại rằng nó sẽ hướng theo hướng đối tượng hơn nếu các lớp được đề cập được xác định riêng (có thể là mẫu), nhưng đây là một chương trình nhỏ, tự chứa và tôi đang cố gắng giữ theo cách đó.

EDIT: Tự khép kín cũng có nghĩa là đó là một chương trình tệp đơn lẻ, do đó không có tệp .h hoặc mã bên ngoài sử dụng lại bất kỳ thứ gì. Tại sao? Vì ACADEMIA (và các hạn chế tùy ý liên quan).

+0

Tại sao 'use' và' typedef' mua cho bạn bất cứ thứ gì? – lcs

+0

Chúng là các lớp riêng, vì vậy tôi không thể nói 'sử dụng Stack = Tree :: Iterator :: Stack;' hoặc một cái gì đó tương tự - 'Iterator' và' Stack' là không thể truy cập. –

+0

Bạn có thể khai báo lớp lồng nhau và sau đó xác định các hàm thành viên của nó trong dòng, khi bạn định nghĩa lớp sau này. Nhưng, tôi nghĩ rằng mã đó có vẻ tốt đẹp. Nếu bạn cũng có một loạt các không gian tên để xử lý _inside_ các định nghĩa hàm, bạn thực sự có thể đặt các khai báo 'using' bên trong mỗi định nghĩa hàm. – SirGuy

Trả lời

3

Bạn hoàn toàn có thể loại bỏ độ phân giải phạm vi bằng using hoặc typedef. Nhưng không phải theo cách truyền thống bởi vì các lớp lồng nhau của bạn được khai báo riêng. Vì vậy, bạn sẽ phải sử dụng thêm using trong phần public của từng lớp lồng nhau để "hiển thị" chúng. Thật không may, này phá vỡ "privateness" trong số họ:

class Tree { 
    class Iterator { 
     class Stack { 
      Stack& operator = (const Stack& p_stack); 
     }; 
    public: 
     using Stack_Out = Stack; 

     // ... 
    }; 
public: 
    using Iterator_Out = Iterator::Stack_Out; 
    //... 

}; 

using Stack = Tree::Iterator_Out; 

Stack& Stack::operator = (const Stack& p_stack) { 
// ... 
} 

LIVE DEMO

Bạn tuy nhiên có thể, loại bỏ mức phạm vi (trừ trường hợp một bên ngoài, tức là, Tree::) với ra phơi bày các lớp lồng nhau tin theo cách sau:

class Tree { 
    class Iterator { 
     friend class Tree; 
     ^^^^^^^^^^^^^^^^^^ 
     class Stack { 
      Stack operator = (const Stack& p_stack); 
     }; 
    public: 

     // ... 
    }; 

    using Stack = Iterator::Stack; 
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

public: 

}; 

Tree::Stack Tree::Stack::operator = (const Stack& p_stack) { 
^^^^^^^^^^^ ^^^^^^^^^^^ 
} 

LIVE DEMO

+0

Các lớp lồng nhau chỉ riêng tư nếu chúng được khai báo trong phần riêng tư. – Deduplicator

+1

Điều này không làm suy yếu toàn bộ vấn đề có các lớp học riêng tư ngay từ đầu? – SirGuy

+0

@Deduplicator trong OP chúng được xác định trong phần riêng tư. – 101010

0

Trước hết, bạn nên giải thích điều bạn muốn đạt được và cách bạn nghĩ phương pháp này phù hợp với nhiệm vụ của bạn. IMHO, cách tiếp cận tốt hơn là tạo các lớp riêng lẻ không lồng nhau và sử dụng chúng trong lớp Ba. Cách tiếp cận này được gọi là "HAS A". Nó là dễ dàng hơn để duy trì và hiểu từ những người khác. Nếu bạn cung cấp thêm chi tiết, chúng tôi có thể đưa ra thiết kế lớp học tốt hơn.

+0

Cảm ơn, tôi đã làm rõ ngữ cảnh ngay bây giờ. –

-2

Bạn có thể để người tiền xử lý giúp bạn:

#define foobar Tree::Iterator::Stack  
foobar& foobar::operator = (const Stack& p_stack) { 
    // ... 
} 
+0

Như tôi đã bị chỉ trích [ở đây] (http://codereview.stackexchange.com/questions/110461/memory-management-for-red-black-tree), các định nghĩa tiền xử lý làm tê liệt thế giới khi được sử dụng một cách không cần thiết. –

+2

hoàn toàn không bao giờ làm điều này. –

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