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

HandBooks Professional Java-C-Scrip-SQL part 100 doc

6 89 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 6
Dung lượng 35,13 KB

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

Nội dung

#include #include "boost/signals.hpp" class slot { public: void operator const { std::cout... #include #include #include #include "boost/signals.hpp" #include "boost/lambda/lambda.

Trang 1

#include <iostream>

#include "boost/signals.hpp"

class slot {

public:

void operator()() const {

std::cout << "Something important just happened!\n";

}

};

int main() {

boost::signal<void ()> sig;

{

boost::signals::scoped_connection s=sig.connect(slot());

}

sig();

}

The boost::signals::scoped_connection s is given a small scope inside of main, and after leaving that scope the signal sig is invoked There

is no output from that, because the scoped_connection has already

terminated the connection between the slot and the signal Using scoped

resources like this simplifies the code and maintenance thereof

Creating Slots Using Bind and Lambda

You've seen how useful and flexible Signals is However, you'll find even more power when you combine Boost.Signals with Boost.Bind and Boost.Lambda Those two libraries, covered in detail in "Library 9: Bind 9" and "Library 10: Lambda 10," help to create function objects on-the-fly That means it is possible to create slots (and slot types) right at the point where they are connected to a

signal, rather than having to write a special, single-purpose class for a slot, create an instance, and then connect it It also puts the slot logic right where it's used rather than in a separate part of the source code Finally, these libraries even make it possible to adapt existing classes that don't provide a function call operator but have other, suitable means for handling signals

In the first example to follow, we'll have a look at how neatly lambda expressions can be used to create a few slot types The slots will be created right in the call to connect The first one simply prints a message to std::cout when the slot is invoked The second checks the value of the string passed through the signal to

Trang 2

the slot If it equals "Signal", it prints one message; otherwise, it prints another message (These examples are rather contrived, but the expressions could perform any kind of useful computation.) The last two slots created in the example will do exactly what double_slot and plus_slot did in an example earlier in the chapter You'll find the lambda versions far more readable

#include <iostream>

#include <string>

#include <cassert>

#include "boost/signals.hpp"

#include "boost/lambda/lambda.hpp"

#include "boost/lambda/if.hpp"

int main() {

using namespace boost::lambda;

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

sig.connect(var(std::cout)

<< "Something happened: " << _1 << '\n');

sig.connect(

if_(_1=="Signal") [

var(std::cout) << "Ok, I've got it\n"]

.else_[

std::cout << constant("Yeah, whatever\n")]);

sig("Signal");

sig("Another signal");

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

sig2.connect(0,_1*=2); // Double it

sig2.connect(1,_1+=3); // Add 3

int i=12;

sig2(i);

assert(i==27);

}

If you aren't yet familiar with lambda expressions in C++ (or otherwise), don't worry if the preceding seems a bit confusingyou may want to read the chapters on Bind and Lambda first and return to these examples If you already have, I am sure that you appreciate the terse code that results from using lambda expressions; and

it avoids cluttering the code with small function objects, too

Now let's take a look at using binders to create slot types Slots must implement a function call operator, but not all classes that would otherwise be suitable as slots

Trang 3

do so In those cases, it's often possible to use existing member functions of

classes, repackaged for use as slots using binders Binders can also help readability

by allowing the function (rather than function object) that handles an event to have

a meaningful name Finally, there are situations in which the same object must respond to different events, each with the same slot signature, but different

reactions Thus, such objects need different member functions to be called for different events In each of these cases, there is no function call operator suitable for connecting to a signal Thus, a configurable function object is needed, and Boost.Bind provides (as the bind facility in Boost.Lambda) the means to do that Consider a signal that expects a slot type that returns bool and accepts an argument of type double Assuming a class some_class with a member

function some_function that has the correct signature, how do you connect some_class::some_function to the signal? One way would be to add a function call operator to some_class, and have the function call operator

forward the call to some_function That means changing the class interface unnecessarily and it doesn't scale well A binder works much better

#include <iostream>

#include "boost/signals.hpp"

#include "boost/bind.hpp"

class some_class {

public:

bool some_function(double d) {

return d>3.14;

}

bool another_function(double d) {

return d<0.0;

}

};

int main() {

boost::signal<bool (double)> sig0;

boost::signal<bool (double)> sig1;

some_class sc;

sig0.connect(

boost::bind(&some_class::some_function,&sc,_1));

sig1.connect(

boost::bind(&some_class::another_function,&sc,_1));

sig0(3.1);

Trang 4

sig1(-12.78);

}

Binding this way has an interesting side effect: It avoids unnecessary copying of some_class instances The binder holds a pointer to the some_class instance and it's the binder that the signal copies Unfortunately, there's a potential

lifetime management issue with this approach: If sc is destroyed and then one of the signals is invoked, undefined behavior results That's because the binder will have a dangling pointer to sc By avoiding the copies, we must also assume the responsibility of keeping the slots alive so long as a connection exists that (indirectly) references them Of course, that's what reference-counting smart

pointers are for, so the problem is easy to solve

Using binders like this is common when using Boost.Signals Whether you use lambda expressions to create your slots or binders to adapt existing classes for use

as slot types, you'll soon value the synergy among Boost.Signals, Boost.Lambda, and Boost.Bind It will save you time and make your code elegant and succinct

Signals Summary

Use Signals when

 You need robust callbacks

 There can be multiple handlers of events

 The connection between the signal and the connected slots should be

configurable at runtime

That Boost.Signals supersedes old-style callbacks should be blatantly clear by now, and this library is one of the best signals and slots implementations available The design pattern that the library captures is well known and has been studied for

a long time, so the domain is mature Some programming languages already have such mechanisms available directly in the languagefor example, delegates and events in NET In C++, the problem is elegantly solved with libraries Signals and slots are used to separate the trigger mechanism of an event from the code that handles it This separation decouples subsystems and makes them more

comprehensible It also solves the problem of updating multiple interested parties when important events take place There are numerous places in a typical program

or library where signals and slots are useful Whether you are writing a GUI

Trang 5

framework or an intrusion detection system for a power plant, Signals is ready to take care of all your signaling needs It is easy to learn how to use, yet it also offers the advanced functionality that is required for complex tasks For example, custom Combiners make it possible to write event mechanisms that are tailor-made for a certain domain

Boost.Signals was written by Douglas Gregor (who incidentally also wrote

Boost.Function) This is a great library; thank you Doug!

Endnotes

2 The Boost.Signals library and the Boost.Regex library are the only libraries covered in this book that actually require compiling and linking for use The process is simple, and it's described in great detail in the online

documentation, so I won't cover it here

3 binary_search has the attractive complexity O(logN)

1.1 Introduction

The Objective-C Pocket Reference is a quick guide to the Objective-C

programming language and some of its fundamental support libraries This

reference takes the form of brief explanations interspersed with examples and definitions If you are experienced with Objective-C, this handbook will supply the definitions and examples you most often need to jog your memory If you are coming to Objective-C from C++ or Java and prefer to jump right in and write code, this book will give you enough explanation to use the language's features appropriately

You should be familiar with C-style languages in order to read this book Objective-C uses C syntax This book focuses only on Objective-C, and assumes that you understand the underlying C code

This handbook progresses in sequence as much as possible, with later sections building on earlier ones, but some parts are necessarily interrelated For example, the section on objects needs to refer to classes and vice versa Both use the

Trang 6

terminology of inheritance Where you see an unfamiliar term used, check the index: it is probably defined elsewhere in the book

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

TỪ KHÓA LIÊN QUAN