1. Trang chủ
  2. » Công Nghệ Thông Tin

HandBooks Professional Java-C-Scrip-SQL part 96 pptx

5 85 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 5
Dung lượng 20,46 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

To start using the library, include the header "boost/signals.hpp".[2] The following example demonstrates the basic properties of signals and slots, including how to connect them and how

Trang 1

Usage

When faced with needing more than one piece of code in a program to handle a given event, typical solutions involve callbacks through function pointers, or directly coded dependencies between the subsystem that fires the event and the subsystems that need to handle it Circular dependencies are a common result of such designs Using Boost.Signals, you gain flexibility and decoupling To start using the library, include the header "boost/signals.hpp".[2]

The following example demonstrates the basic properties of signals and slots, including how to connect them and how to emit the signal Note that a slot is something that you provide, either a function or a function object that is

compatible with the function signature of the signal In the following code, we create both a free function, my_first_slot, and a function object, my_second_slot; both are then connected to the signal that we create

#include <iostream>

#include "boost/signals.hpp"

void my_first_slot() {

std::cout << "void my_first_slot()\n";

}

class my_second_slot {

public:

void operator()() const {

std::cout <<

"void my_second_slot::operator()() const\n";

}

};

int main() {

boost::signal<void ()> sig;

sig.connect(&my_first_slot);

sig.connect(my_second_slot());

std::cout << "Emitting a signal \n";

sig();

}

We start by declaring a signal, which expects slots that return void and take no arguments We then connect two compatible slot types to that signal For one, we call connect with the address of the free function, my_first_slot For the other, we default-construct an instance of the function object my_second_slot and pass it to

Trang 2

connect These connections mean that when we emit a signal (by invoking sig), the two slots will be called immediately

sig();

When running the program, the output will look something like this:

Emitting a signal

void my_first_slot()

void my_second_slot::operator()() const

However, the order of the last two lines is unspecified because slots belonging to the same group are invoked in an unspecified order There is no way of telling which of our slots will be called first Whenever the calling order of slots matters, you must put them into groups

Grouping Slots

It is sometimes important to know that some slots are called before others, such as when the slots have side effects that other slots might depend upon Groups is the name of the concept that supports such requirements It is a signal template

argument named Group that is, by default, int The ordering of Groups is

std::less<Group>, which translates to operator< for int In other words, a slot

belonging to group 0 is called before a slot in group 1, and so on Note, however, that slots in the same group are called in an unspecified order The only way to exactly control the order by which all slots are called is to put every slot into its own group

A slot is assigned to a group by passing a Group to signal::connect The group to which a connected slot belongs cannot be changed; to change the group for a slot,

it must be disconnected and then reconnected to the signal in the new group

As an example, consider two slots taking one argument of type int&; the first doubles the argument, and the second increases the current value by 3 Let's say that the correct semantics are that the value first be doubled, and then increased by

3 Without a specified order, we have no way of ensuring these semantics Here's

an approach that works on some systems, some of the time (typically when the moon is full and it's Monday or Wednesday)

#include <iostream>

#include "boost/signals.hpp"

Trang 3

class double_slot {

public:

void operator()(int& i) const {

i*=2;

}

};

class plus_slot {

public:

void operator()(int& i) const {

i+=3;

}

};

int main() {

boost::signal<void (int&)> sig;

sig.connect(double_slot());

sig.connect(plus_slot());

int result=12;

sig(result);

std::cout << "The result is: " << result << '\n';

}

When running this program, it might produce this output:

The result is: 30

Or, it might produce this:

The result is: 27

There's simply no way of guaranteeing the correct behavior without using groups

We need to ensure that double_slot is always called before plus_slot That requires that we specify that double_slot belongs to a group that is ordered before

plus_slot's group, like so:

sig.connect(0,double_slot());

sig.connect(1,plus_slot());

This ensures that we'll get what we want (in this case, 27) Again, note that for slots belonging to the same group, the order with which they are called is

unspecified As soon as a specific ordering of slot invocation is required, make sure to express that using different groups

Trang 4

Note that the type of Groups is a template parameter to the class signal, which makes it possible to use, for example, std::string as the type

#include <iostream>

#include <string>

#include "boost/signals.hpp"

class some_slot {

std::string s_;

public:

some_slot(const std::string& s) : s_(s) {}

void operator()() const {

std::cout << s_ << '\n';

}

};

int main() {

boost::signal<void (),

boost::last_value<void>,std::string> sig;

some_slot s1("I must be called first, you see!");

some_slot s2("I don't care when you call me, not at all \

It'll be after those belonging to groups, anyway.");

some_slot s3("I'd like to be called second, please.");

sig.connect(s2);

sig.connect("Last group",s3);

sig.connect("First group",s1);

sig();

}

First we define a slot type that prints a std::string to std::cout when it is invoked Then, we get to the declaration of the signal Because the Groups parameter comes after the Combiner type, we must specify that also (we'll just declare the default)

We then set the Groups type to std::string

boost::signal<void (),boost::last_value<void>,std::string> sig;

We accept the defaults for the rest of the template parameters When connecting the slots s1, s2, and s3, the groups that we create are lexicographically ordered (because that's what std::less<std::string> does), so "First group" precedes "Last group" Note that because these string literals are implicitly convertible to

std::string, we are allowed to pass them directly to the connect function of signal Running the program tells us that we got it right

Trang 5

I must be called first, you see!

I'd like to be called second, please

I don't care when you call me, not at all

It'll be after those belonging to groups, anyway

We could have opted for another ordering when declaring the signal typefor

example, using std::greater

boost::signal<void (),boost::last_value<void>,

std::string,std::greater<std::string> > sig;

Had we used that in the example, the output would be

I'd like to be called second, please

I must be called first, you see!

I don't care when you call me

Of course, for this example, std::greater produces an ordering that leads to the wrong output, but that's another story Groups are useful, even indispensable, but it's not always trivial to assign the correct group values, because connecting slots isn't necessarily performed from the same location in the code It can thus be a problem to know which value should be used for a particular slot Sometimes, this problem can be solved with disciplinethat is, commenting the code and making sure that everyone reads the commentsbut this only works when there aren't many places in the code where the values are assigned and when there are no lazy

programmers In other words, this approach doesn't work Instead, you need a central source of group values that can be generated based upon some supplied value that is unique to each slot or, if the dependent slots know about each other, the slots could provide their own group value

Now that you know how to deal with issues of slot call ordering, let's take a look at different signatures for your signals You often need to pass additional information along about important events in your systems

Signals with Arguments

Often, there is additional data to be passed to a signal For example, consider a temperature guard that reports drastic changes in the temperature Just knowing

Ngày đăng: 06/07/2014, 03:20