2017-03-29 33 views
8

tôi đang làm việc trên một số mã, nơi tôi gặp phải một tình huống tương tự như thế này:Cấp quyền truy cập cho nhà xây dựng riêng tư mà không có bạn bè?

struct Bar; 

struct Foo{ 
    friend struct Bar; 
private: 
    Foo(){} 
    void f(){} 
    void g(){} 
}; 

struct Bar { 
    Foo* f; 
    Bar() { f = new Foo();} 
    ~Bar() { delete f;} 
}; 

int main(){ 
    Bar b; 
} 

Tôi muốn có Bar không như friend của Foo, bởi vì bên cạnh Foo s constructor Bar không cần truy cập vào bất kỳ của Foo phương thức riêng tư (và do đó không được có quyền truy cập). Có cách nào để chỉ cho phép Bar tạo Foo giây mà không cần phải kết bạn với họ không?

PS: nhận thấy rằng câu hỏi có thể không rõ ràng 100%. Tôi không quan tâm nếu nó là thông qua bạn bè hay không, chỉ là một thực tế rằng tất cả các Bar có quyền truy cập vào tất cả các phương pháp tư nhân là làm phiền tôi (mà thường là trường hợp với friends) và đó là những gì tôi muốn tránh. May mắn là không có câu trả lời nào cho đến nay có vấn đề với công thức tệ hại đó.

Trả lời

9

Đây chính xác là những gì attorney-client thành ngữ dành cho:

struct Bar; 

struct Foo { 
    friend struct FooAttorney; 
private: 
    Foo(){} 
    void f(){} 
    void g(){} 
}; 

class FooAttorney { 
    static Foo* makeFoo() { return new Foo; } 
    friend struct Bar; 
}; 

struct Bar { 
    Foo* f; 
    Bar() { f = FooAttorney::makeFoo();} 
    ~Bar() { delete f;} 
}; 

int main(){ 
    Bar b; 
} 

Trong một mã bắt chước thời trang cuộc sống, lớp tuyên bố một luật sư mà sẽ dàn xếp những bí mật đó là sẵn sàng chia sẻ với các bên lựa chọn.

+0

Cảm ơn bạn đã chuyển nhận xét "Không. Nhưng ..." thành một câu trả lời hay. Tôi đã sợ có một lý do tôi không thể sử dụng nó cho nhà xây dựng – user463035818

+0

@ tobi303 Xin lỗi về sự sợ hãi. Hai giây sau khi nhận xét tôi nhận ra tôi đang cố trả lời câu hỏi của bạn trong một bình luận. – StoryTeller

5

Nếu bạn không muốn giới thiệu một lớp học khác, bạn có thể thu nhỏ vòng kết nối của tình bạn và tạo thành người bạn của Bar 's constructor Foo' s friend. Nó đòi hỏi 'định nghĩa s sẽ có sẵn để Foo, và nó vẫn mang lại cho Bar' Bar s constructor truy cập không hạn chế để thực hiện tin Foo 's:

struct Foo; 

struct Bar { 
    Foo* f; 
    Bar(); 
    ~Bar(); 
}; 

struct Foo{ 
    friend Bar::Bar(); 
private: 
    Foo(){} 
    void f(){} 
    void g(){} 
}; 

Bar::Bar() : f(new Foo()) { 
} 

Bar::~Bar() { 
    delete f; 
} 

này không đạt được chính xác những gì bạn muốn, nhưng nó làm cho bạn một nhắm mục tiêu nhiều hơn.

+0

tại sao không chính xác những gì tôi muốn? Thật không may hiện tại 'Bar' cần biết định nghĩa' Foo ', nhưng điều đó có thể thay đổi một lần nếu sửa vấn đề tình bạn. – user463035818

+1

@ tobi303 Đây không phải là chính xác những gì bạn muốn, bởi vì bạn yêu cầu hạn chế những gì một người bạn có thể làm, trong khi cách tiếp cận này hạn chế ai là người bạn thay thế. Các nhà xây dựng của 'Bar' vẫn giữ lại đầy đủ các truy cập do tình bạn của nó với' Foo'. Tất nhiên, tùy thuộc vào một tình huống này có thể không phải là một điều xấu. – dasblinkenlight

+0

ah vâng, hiểu rồi. Trên thực tế tôi sẽ không nhớ nếu nó có thể không có bạn bè. Tôi không thích khái niệm của bạn bè ở tất cả (tôi có nghĩa là một C + + một;).Với cách tiếp cận này ít nhất là phạm vi mà tôi phải cẩn thận để không làm điều gì đó ngu ngốc được giới hạn ở mức tối thiểu – user463035818

3

Một cách đã xảy ra với tôi là phải có một nội class mà làm Bar người bạn của mình vì vậy chỉ Bar có thể tạo ra nó và rằng nội class có thể được sử dụng như một tham số bổ sung để Foo constructor vì vậy chỉ bạn bè của class có thể gọi nó.

class Foo 
{ 
public: 
    // only friends of the special key can invoke the constructor 
    // or any member function that includes it as a dummy parameter 
    class special_key {friend class Bar; special_key(){}}; 

    // making special_key a dummy parameter makes sure only friends of 
    // the special key can invoke the function 
    Foo(special_key) {} 
    void f(){} 
    void g(){} 
}; 

class Bar 
{ 
public: 
    // only Bar functions can create the special key 
    Bar() { f = std::make_unique<Foo>(Foo::special_key()); } 

private: 
    std::unique_ptr<Foo> f; 
}; 

Cũng như hạn chế quyền truy cập vào các chức năng cụ thể phương pháp này cũng cho phép sử dụng con trỏ thông minh make chức năng mà bạn trực tiếp thì không.

+0

Tôi đã suy nghĩ theo hướng đó trước tiên, mặc dù giải pháp của tôi có thể đã trở nên lộn xộn hơn rất nhiều – user463035818

+1

@ tobi303. cũng cho phép bạn sử dụng con trỏ thông minh mà tình bạn trực tiếp không. – Galik

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