Наследование

Stashevckiy

Well-known member
23.10.2011
56
0
#1
Привет! Подскажите, пожалуйста, как из производного класса получить значение private - переменной базового класса? Спасибо!
 

lazybiz

Well-known member
03.11.2010
1 339
0
#2
Это не допустимо, можно получить доступ только к protected и public.

Можно сделать вот так:
C++:
#include <iostream>

using namespace std;

class A {
friend class B;
private:
int		a;
};

class B : public A
{
public:
void test() {
A	a;
a.a = 10;
cout << a.a << endl;
}
};

int main()
{
B	x;
x.test();
return 0;
}
это не совсем то что ты хотел, тут доступ к private-члену осуществляется посредством объявления класса B дружественным.
 

Stashevckiy

Well-known member
23.10.2011
56
0
#3
просто вот что именно меня интересует. Есть такого рода задача : реализация паттерна Посредник. К примеру, есть 4 класса -> User, Mediator, ClassA, ClassB. Обьект User принимает строку. И мне нужно эту строку, которую получил обьект User передать в ClassA, ClassB посредством класса Mediator. По идее же, паттерн посредник подразумевает наслевоние.. Задачу эту я сделал, но чуть схитрив, а так не интересно.

Собственно, вот программа.

Здесь при создании обьекта User происходит вызов обьекта Mediator и передача ему указателя на строку( ну или же строки, чтобы понятней было). Конструктор класса Mediator в свою очередь вызывает конструктор класса ClassA, и через указатель передает в него строку, полученную классом Mediator, и здесь же происходит передача этой строки в класс B, но посредством использования композиции...А это вроде не круто как - то )) Вот такие дела..


C++:
#ifndef USER_H
#define USER_H

class User : public Mediator
{
public: 
User( const char * = 0 );

private:
char * temp;
};

User::User(const char * variable):Mediator( variable )
{
temp = new char [ strlen(variable) + 1 ];
strcpy( temp, variable );
cout<<"\C_User ---> "<<temp<<"\n"<<endl;
}
#endif

#ifndef MEDIATOR_H
#define MEDIATOR_H

#include "ClassB.h"

class Mediator: public ClassA
{
public:
Mediator( const char * = 0);
ClassB obj;

private:
char * storage;
};

Mediator::Mediator(const char * variable) : ClassA ( variable)
{
storage = new char [ strlen(variable) + 1 ];
strcpy( storage, variable);
obj.setTT(variable);
}
#endif

#ifndef CLASSA_H
#define CLASSA_H

#include "iostream"
using namespace std;

class ClassA
{
public:
ClassA( const char * = 0);
char * var;
};

ClassA::ClassA( const char * temp)
{
var = new char [ strlen(temp) + 1 ];
strcpy(var, temp);
cout<<"ClassA ---> "<<var<<"\n"<<endl;
}
#endif

#ifndef CLASSB_H
#define CLASSB_H

#include "iostream"
using namespace std;

class ClassB
{
public:
ClassB( const char * = 0);
void setTT( const char * );

private:
char * tt;
};

ClassB::ClassB( const char * temp)
{
}
void ClassB::setTT(const char * v)
{
tt = new char [ strlen(v) + 1 ];
strcpy(tt, v);
cout<<"\ClassB ---> "<<tt<<"\n"<<endl;
}
#endif

#include "iostream"
using namespace std;

#include "ClassA.h"
#include "ClassB.h"
#include "Mediator.h"
#include "User.h"

void main()
{
User u("You don't like - you don't buy!");
}

А как сделать так, чтобы композицию заменить наследованием, я ума не приложу. Если пронаследовать классом claasB класс Mediator, то происходить ошибка, в которой говорится, что невозможно определить базовый класс ((
screen.png
 

Вложения

R

rrrFer

#4
много кода, я невчитывался - попробуй сжать(оставь самое главное).
Зато вчитался в первый пост:
как из производного класса получить значение private - переменной базового класса?
1. Получить значение можно при помощи public метода, например.
C++:
class A{
/...
public:
int getVar();
private:
int var;
//...
};
int A ::getVar() {
return var;
}

calss B: public A {
//...
};
В примере для того, чтобы "получить значение private - переменной базового класса" класса B(базовый А) нужно вызвать метод getVar().

2. Если нужен полноценный доступ к полю базового класса - используй protected.

3. Вариант лазибиз тоже выход, но дружбу я бы не использовал. С некоторых точек зрения она нарушает принцип инкапсуляции(в словесных баталиях на эту тему я участвовать не буду), хотя иногда без нее не обойтись(но вряд-ли это ваш случай).
 

lazybiz

Well-known member
03.11.2010
1 339
0
#5
Я вообще не понимаю зачем тебе член класса private делать. Думаю что лучше всего будет:
2. Если нужен полноценный доступ к полю базового класса - используй protected.
C++:
#include <iostream>

using namespace std;

class A {
protected:
int	x;
};

class B : public A {
public:
B( int v ) { x = v; }
void print() {
cout << x << endl;
}
};

int main()
{
B	b( 123 );
b.print();
return 0;
}
 

Stashevckiy

Well-known member
23.10.2011
56
0
#6
Товарищи, почему же ни кто не хочет прочитать второй пост и вникнуть в суть поставленной задачи... Смотрите, что нужно организовать:

1) Явно создать и инициализировать объект класса User.
2) Получить значение обьекта User и сохранить в классе MEdiator - посредник.
3) Получить сохраненное значение обьекта User из класса Mediator и сохранить в классе classA
4) Получить сохраненное значение обьекта User из класса Mediator и сохранить в классе classB

Я согласен, что не обязательно использовать private, но меня интересует, как реализовать выше перечисленные пункты при явной инициализации только обьекта User. Получится ли получить значение переменной из класса User в класс Mediator и последующие, если не создается явно обьекты последних, а в этих классах описан только процесс доступа к соответствующим переменным???
 

lazybiz

Well-known member
03.11.2010
1 339
0
#7
Держи.
C++:
#include <iostream>

using namespace std;

class User {
friend class Mediator;
public:
User( int v ) { x = v; }
private:
int	x;
};

class Mediator {
friend class ClassA;
friend class ClassB;
public:
void getUser( User U ) { x = U.x; };
protected:
int	x;
};

class ClassA {
public:
void getMediator( Mediator M ) { x = M.x; };
void print() { cout << x << endl; }
protected:
int	x;
};

class ClassB {
public:
void getMediator( Mediator M ) { x = M.x; };
void print() { cout << x << endl; }
protected:
int	x;
};

int main()
{
User		U( 123 );
Mediator	M;
ClassA		A;
ClassB		B;

M.getUser( U );
A.getMediator( M );
B.getMediator( M );

A.print();
B.print();

return 0;
}
Добавлено: Полностью подходит под твое описание.
 

Stashevckiy

Well-known member
23.10.2011
56
0
#8
Держи.
C++:
#include <iostream>

using namespace std;

class User {
friend class Mediator;
public:
User( int v ) { x = v; }
private:
int	x;
};

class Mediator {
friend class ClassA;
friend class ClassB;
public:
void getUser( User U ) { x = U.x; };
protected:
int	x;
};

class ClassA {
public:
void getMediator( Mediator M ) { x = M.x; };
void print() { cout << x << endl; }
protected:
int	x;
};

class ClassB {
public:
void getMediator( Mediator M ) { x = M.x; };
void print() { cout << x << endl; }
protected:
int	x;
};

int main()
{
User		U( 123 );
Mediator	M;
ClassA		A;
ClassB		B;

M.getUser( U );
A.getMediator( M );
B.getMediator( M );

A.print();
B.print();

return 0;
}
о, спасибо за пример! Сейчас попробую разобраться. Выглядит не сложно ;)
 

Stashevckiy

Well-known member
23.10.2011
56
0
#9
Все получилось. Переделал под работу со строками. lazybiz, а скажи ка, если бы нужно было реализовать подобную задачу на API, т.е. при роботе с окнами, ты бы тоже использовал композицию, или в API есть по изощренней методы для такого рода задач?
 
R

rrrFer

#10
зачем нам нужен посредник в данном случае?
прочитал это:
1) Явно создать и инициализировать объект класса User.
2) Получить значение обьекта User и сохранить в классе MEdiator - посредник.
3) Получить сохраненное значение обьекта User из класса Mediator и сохранить в классе classA
4) Получить сохраненное значение обьекта User из класса Mediator и сохранить в классе classB
как я понимаю суть в том что есть N-потребителей, которых работают не с самим источником информации, а с посредником. Зачем? - наверно источники информации могут меняться(например, вводил пользователь данные клавиатурой, а начал вводить голосом), тогда при взаимодействии потребителя с источником напрямую, на потребителя возлагается задача определения "правильного" источника. Ну а тут предлагается решить 1 раз эту проблему посреднику, а потребителям использовать решение.

Ну это мои предположения. Если я все верно понял - то изощренных средств в АПИ не знаю, но в QT есть удобный механизм сигналов и слотов.
Для решения надо создать класс Посредник и класс Потребитель.
в Посредник добавляем слот для получения данных от источника. Слот- это функция, которая вызывается по сигналу о приходе данных. в Посрденик добавляем сигнал для оповещения потребителей о том, что новые данные пришли и успешно сохранены в Посреднике.
в Потребитель добавляем слот для получения данных от Посредника.

все это соединяем методом connect примерно так:
C++:
Посредник Пс1;
Потребитель Пт1, Пт2;
connect( Некоторая_Кнопка, SIGNAL(pressed()), Пс1, SLOT(Прием_данных()));
connect( Пс1, SINGAL(данные_сохранены_посредником()), Пт1, SLOT(Новые_данные())); 
connect( Пс1, SINGAL(данные_сохранены_посредником()), Пт2, SLOT(Новые_данные()));
как то так.
 

lazybiz

Well-known member
03.11.2010
1 339
0
#11
Все получилось. Переделал под работу со строками. lazybiz, а скажи ка, если бы нужно было реализовать подобную задачу на API, т.е. при роботе с окнами, ты бы тоже использовал композицию, или в API есть по изощренней методы для такого рода задач?
Если честно, то я вообще не понял что должна делать твоя программа, а просто дал тебе то что ты просил.
О каких API и про какую композицию ты говоришь?