2013-11-24 3 views
2

Предположит, что у меня есть свои классы как:Установка для чтения свойства из другого класса

namespace scope 
{ 

class A 
{ 
private: 
    int a; 
public: 
    ... 
}; 

class B 
{ 
public: 
    ... 
    A method(); 
    ... 
}; 

}; 

определение метода:

A B::method() 
{ 
    A object; 
    object.a = 3; // private member access error 
        // access via object (pointer) error if inheritance is used 
    return object; 
} 

Наиболее распространенный способ решить ошибку доступа является использование сеттеров + добытчиков.

Однако я не хочу, чтобы какой-либо другой ресурс (или кто-то из API) устанавливал A.a, поэтому для этого случая запрещено использование общего метода set .

может быть общедоступным, но он должен быть доступен только для чтения со стороны API. Он должен быть читать + писать со стороны источника, потому что, например, я хочу установить его с помощью B::method. Как я могу достичь такого поведения?

Я пробовал наследование, а также отношение друзей. Я также играл с immutable и const объявлениями о собственности. Проблема с ними заключается в том, что когда я объявляю объект A со стандартным конструктором, для свойства задано некоторое значение, например -918316838410 (что может возникнуть из-за того, что я не использую extern, я не уверен) и не может быть установлен по method позже.

Любые идеи будут оценены. Заранее спасибо.

+5

Идеи 1, определить 'A' с открытым конструктором' explicit', который принимает 'int'. Идея 2, сделайте 'B' другом' A'. Вы говорите, что вы попробовали «друг», но я подозреваю, что вы не очень старались. –

+2

Конструкция по умолчанию для int - неопределенное значение. Если вы хотите что-то еще, добавьте соответствующие конструкторы. (например, конструктор no-arg, который устанавливает хорошее значение, или конструктор int, который принимает аргумент и использует его). Что касается явной, его ненужной, но часто хорошей идеи для конструктора с одним аргументом, чтобы избежать непреднамеренного автоматического преобразования – RichardPlunkett

ответ

2

Вы хотите, чтобы у B был доступ к A, который вы не хотите, чтобы другие люди имели?

То есть дружба.

Добавить friend class B, в определение класса A, и все будет счастье.

Кстати, общие примеры для этого - это когда я использую несколько классов для создания единого интерфейса. Например: такие вещи, как список <> и карта <> обычно нужны классы узлов, и эти классы часто хотят друг друга друг друга. Это нарушение инкапсуляции отлично, поскольку они действительно являются одним большим классом с логической точки зрения.

Будьте предупреждены, что большинство людей должны использовать друзей редко или никогда, главным образом для библиотек, а не для общего программирования.

1

Как и Ричард, вы можете использовать дружбу. Но имейте в виду, что, когда вам нужна дружба, вы, вероятно, должны подумать о своем дизайне. Как сказал Ричард, возможно, что установка как параметра конструктора A должна делать именно то, что вы хотите.

Вот рабочий пример с дружбой:

#include <iostream> 
namespace scope 
{ 
class A{ 
friend class B; 
private: 
    int a; 
public: 
    void print(){ 
     std::cout << a << std::endl; 
    } 
}; 

class B{ 
public: 
    A method(){ 
     A a; 
     a.a=3; 
     return a; 
    } 
}; 

int main(){ 
    scope::B b; 
    scope::A a = b.method(); 
    a.print(); //just to see it works... 
} 

Вот способ сделать то же самое без дружбы и поддержание частного (Ok уродливой :-)

#include <iostream> 
namespace scope 
{ 
class B; 
class A 
{ 
private: 
    int a; 
public: 
    void print(){ 
     std::cout << a << std::endl; 
    } 
    // A way to only allow B instances to give a correct value 
    // of "a" member 
    void pleaseClassBSetMyPrivateMember(B& b); 
}; 

class B 
{ 
public: 
    A method(){ 
     A a; 
     a.pleaseClassBSetMyPrivateMember(*this); 
     return a; 
    } 

    int computeValueForMemberOfClassA(A& a){ 
     // you can access public members of a to 
     // calculate the proper value of a.a member 
     return 3; 
    } 

}; 

void A::pleaseClassBSetMyPrivateMember(B& b) 
{ 
    // ask for class B object the correct value for member a 
    a = b.computeValueForMemberOfClassA(*this); 
} 

}; 
Смежные вопросы