Сделать их Singleton не совсем плохая идея, но лично я бы не стал делать это именно так. Я предпочел бы передать ссылку на другую форму. Вот пример.
Form1 запускает Form2 для открытия. Form2 имеет перегруженный конструктор, который принимает форму вызова в качестве аргумента и предоставляет ссылку на члены Form2. Это решает проблему связи. Например, я обнаружил свойство Label как общедоступное в Form1, которое было изменено в Form2.
При таком подходе вы можете общаться по-разному.
Ссылка для загрузки для примера Project
// Ваша форма1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2(this);
frm.Show();
}
public string LabelText
{
get { return Lbl.Text; }
set { Lbl.Text = value; }
}
}
// Ваша форма2
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private Form1 mainForm = null;
public Form2(Form callingForm)
{
mainForm = callingForm as Form1;
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
this.mainForm.LabelText = txtMessage.Text;
}
}
Указатель на член позволяет вам иметь указатель, относящийся к определенному классу.
Допустим, у вас есть контактный класс с несколькими телефонными номерами.
class contact
{
phonenumber office;
phonenumber home;
phonenumber cell;
};
Идея состоит в том, что если у вас есть алгоритм, который должен использовать номер телефона, но решение о том, какой номер телефона следует принимать за пределами алгоритма, указатели на член решают проблему:
void robocall(phonenumber contact::*number, ...);
Теперь вызывающий robocall может решить, какой тип используемого телефонного номера:
robocall(&contact::home, ...); // call home numbers
robocall(&contact::office, ...); // call office number
. *
и -> *
вступают в игру, когда у вас есть указатель. Итак, внутри robocall вы должны сделать:
contact c = ...;
c.*number; // gets the appropriate phone number of the object
или:
contact *pc = ...;
pc->*number;
Ознакомьтесь с разделом C ++ FAQ Lite по указателям на функции-члены . Найдите конкретные «операторы», о которых вы говорите (в большинстве браузеров Ctrl-F открывает диалоговое окно «Поиск / поиск», которое позволяет вам искать текст на веб-странице), и это должно помочь вам лучше понять вещи.
Излишне упрощенный ответ - эти операторы позволяют вызывать функции-члены как «обычные» функции (по крайней мере, это выглядит так же с точки зрения конечного пользователя). Пример из реального мира - они часто используются в различных реализациях обратного вызова.
Нет такого оператора, как :: *
, и никогда не было. Я не знаю, где это у тебя.
Что касается -> *
и . *
- это операторы разыменования для указателей типа указатель на член .
struct S {
int i;
};
int main() {
int S::*pi = &S::i; // pointer of pointer-to-member type
S s;
S* ps = &s;
s.*pi = 0; // operator `.*` used
assert(s.i == 0);
ps->*pi = 1; // operator `->*` used
assert(s.i == 1);
}
Насчет того, что такое указатели на члены ... что по этому поводу говорится в вашей любимой книге по C ++?
Они позволяют вам иметь указатели на функции-члены (и переменные-члены), которые привязаны к конкретному экземпляру класса.
Указатели на функции-члены могут быть полезны для таких вещей, как облегченные реализации паттерна состояния. В общем, в любой момент, когда вы хотите изменить поведение объекта во времени, не прибегая к переключению всего объекта, вы можете рассмотреть возможность использования указателей на функции-члены.
Указатели на переменные-члены могут быть использованы, если вы хотите, например, реализовать общий алгоритм поиска в массиве структур записи, имеющей определенное значение для заданного поля.
Они относятся к указателям на члены и указателям на функции-члены.
struct Foo {
int a() { return 1; }
int b() { return 2; }
int c;
};
int main() {
Foo f;
f.c = 3;
typedef int (Foo::*member_fn)(); // pointer-to-member-function
typedef int (Foo::*data_member); // pointer-to-member
member_fn mf = &Foo::a;
(f.*mf)(); // calls the member function pointed to by mf. returns 1
mf = &Foo::b;
(f.*mf)(); // This time, returns 2, since mf points to b
Foo *fp = &f;
(fp->*mf)(); // same thing, via pointer to f instead of object/reference f.
data_member dm = &Foo::c;
f.*dm; // is 3
f.*dm = 5;
f.c; // is now 5.
Foo f2; // another instance
f2.c = 12;
f2.*dm; // is 12. Same pointer-to-member, different object.
}
Хотя это может выглядеть как оператор, ::*
не является оператором. Это оператор ::
и модификатор типа *
operator, расположенные рядом друг с другом. Чтобы доказать это, не прибегая к чтению стандарта, попробуйте добавить пробелы: :: *
компилируется, . *
не компилируется, -> *
.
Что касается того, для чего они действительно полезны - тот же принцип, что и с указателями функций. Вы не будете использовать их так, как я описал выше, в ситуации, когда вы можете просто вызвать функцию по имени, но вы можете передавать их в качестве параметров или возвращать из функций, хранить их или выбирать одну из нескольких на основе сложной логики.
Если это поможет, я считаю, что синтаксис выбран так, что хотя .*
является неделимым единичным оператором, вы можете представить, что *dm
"означает" c
, член, на который указывает dm. Так что если dm
указывает на c
, то f.*dm
- то же самое, что f.c
.