zoukankan      html  css  js  c++  java
  • 第十九章 特殊工具与技术

    19.1

    #include <iostream>
    #include <cstdlib>
    
    using namespace std;
    
    void* operator new(size_t n)
    {
    	if (void *p = malloc(n))
    		return p;
    	else
    		throw bad_alloc();
    } 
    
    void operator delete(void *p) noexcept
    {
    	free(p);
    }
    
    int main()
    {
    	int *ps = new int;
    	delete ps;
    	return 0;
    }
    

      

    19.2

    allocator类将使用我们自定义的版本替换标准库定义的版本,来获取/释放存储空间。

    19.3

    (a):失败,pa指向派生类C,而B是C的基类,故无法转换

    (b):成功

    (c):失败,同(a)

    其他人的答案:

    (a):正确,pa指向C构造的对象的A部分

    (b):失败,pb指向的对象不包含C对象

    (c):正确

    19.4

    	A *pa = new C;		//pa指向C,*pa的类型是C 
    	try {
    		C &c = dynamic_cast<C&>(*pa);
    		//使用C的成员 
    		
    	} catch(bad_cast) {
    		//使用A的成员 
    	}
    

      

    19.5

    使用dynamic_cast运算符代替虚函数:使用基类对象的指针或引用执行某个(不是虚函数)派生类操作时

    19.6

    	Query_base *q = new AndQuery(Query("val1"), Query("val2"));
    	AndQuery a(Query("ss1"), Query("ss2"));
    	if (typeid(*q) == typeid(a))
    		cout << "success
    ";
    	else
    		cout << "failure
    ";
    

      

    19.7

    	Query_base q;
    	AndQuery a(Query("ss1"), Query("ss2"));
    	try {
    		AndQuery aa = dynamic_cast<AndQuery&>(q);
    		cout << "success
    ";
    	} catch (bad_cast) {
    		cout << "failure
    ";
    	}
    

      

    19.8

        Query_base *pb1 = new AndQuery(Query("value1"), Query("value2"));  
        Query_base *pb2 = new OrQuery(Query("value1"), Query("value2")); 
        if (typeid(*pb1) == typeid(*pb2))  
            cout << "pb1与pb2指向的对象类型相同" << endl;  
        else  
            cout << "pb1与pb2的动态类型不相同" << endl;  
        if (typeid(*pb1) == typeid(AndQuery))  
            cout << "pb1的动态类型是AndQuery" << endl;  
        else  
            cout << "pb1的动态类型并非是AndQuery" << endl;  
        if (typeid(*pb2) == typeid(AndQuery))  
            cout << "pb2的动态类型是AndQuery" << endl;  
        else  
            cout << "pb2的动态类型并非是AndQuery" << endl;
    

      

    19.9

    #include <iostream>
    #include <typeinfo>
    
    using namespace std;
    
    int main()
    {
    	int i = 2, a[10] = {0};
    	double d = 0;
    	string s;
    	cout << typeid(i).name() << endl
    		 << typeid(a).name() << endl
    		 << typeid(d).name() << endl
    		 << typeid(s).name() << endl;
    	return 0;
    }
    

      

    19.10

    (a):类型A*

    (b):类型C*

    (c):类型B

    19.11

    普通的数据指针:指向一个对象

    指向数据成员的指针:指示的是类的成员(而非类的对象)

    19.12

    #include <iostream>
    #include <typeinfo>
    
    using namespace std;
    
    class Screen {
    public:
    	typedef string::size_type pos;
    	Screen(): cursor(0), height(0), width(0) {}
    	char get_cursor() const { return contents[cursor]; }
    	char get() const;
    	char get(pos ht, pos wd) const;
    	static pos Screen::* co() { return &Screen::cursor; }
    //	pos Screen::*p = &Screen::cursor;
    private:
    	string contents;
    	pos cursor;
    	pos height, width;
    };
    
    
    int main()
    {
    	Screen scr;
    	auto p = scr.co();
    	auto ans = scr.*p;
    	cout << ans << endl;
    	return 0;
    }
    

      

    19.13

    类型:const string Sales_data::*

    示例:const string Sales_data::*p = &Sales_data::bookNo;

    19.14

    第一个合法:pmf为指向Screen类成员函数get_cursor的指针

    第二个不合法:get函数存在重载的问题,我们必须显式地声明函数类型以明确指出我们想要使用的是哪个函数

    修正:

    	char (Screen::*pmf)(Screen::pos, Screen::pos) const;
    	pmf = &Screen::get;
    	//way2
    	using Action = char (Screen::*)(Screen::pos, Screen::pos) const;
    	Action pmf = &Screen::get;
    

      

    19.15

    指向成员函数的指针:在成员函数和指向该成员的指针之间不存在自动转换规则

    19.16

    	using Action = double (Sales_data::*)() const;
    

      

    19.17

    char get() const { return contents[cursor]; }//using Action_c_v = char (Screen::*)()const;  
    char get_cursor() const { return contents[cursor]; }//同上  
    inline char get(pos ht, pos wd) const;//using Action_c_uu = char (Screen::*)(pos,pos)const;  
    Screen &move(pos r, pos c);//using Action_Screen_uu = Screen &(Screen::*)(pos,pos); 
    

      

    19.18

    	int a = count_if(svec.begin(), svec.end(), bind(&string::empty, _1));
    

      

    19.21

    #include <iostream>
    
    using namespace std;
    
    class Token {
    public:
    	Token(): tok(INT), ival(0) { }
    	Token(const Token &t): tok(t.tok) { copyUnion(t); }
    	Token &operator=(const Token&);
    	~Token() { if (tok == STR)	sval.~string(); }
    	Token &operator=(const string&);
    	Token &operator=(char);
    	Token &operator=(int);
    	Token &operator=(double);
    private:
    	enum {INT, CHAR, DBL, STR} tok;
    	union {
    		char cval;
    		int ival;
    		double dval;
    		string sval;
    	};
    	void copyUnion(const Token&);
    }; 
    
    void Token::copyUnion(const Token &t)
    {
    	switch (t.tok) {
    		case INT: 
    			ival = t.ival;
    			break;
    		case CHAR:
    			cval = t.cval;
    			break;
    		case DBL:
    			dval = t.dval;
    		case STR:
    			new(&sval) string(t.sval);
    			break;
    	}
    }
    
    Token &Token::operator=(const Token &t)
    {
    	if (tok == STR && t.tok != STR)
    		sval.~string();
    	else if (tok == STR && t.tok == STR)
    		sval = t.sval;
    	else
    		copyUnion(t);
    	tok = t.tok;
    	return *this;
    }
    
    Token &Token::operator=(int i)
    {
    	if (tok == STR)
    		sval.~string();
    	ival = i;
    	tok = INT;
    	return *this;
    }
    
    Token &Token::operator=(double d)
    {
    	if (tok == STR)
    		sval.~string();
    	dval = d;
    	tok = DBL;
    	return *this;
    }
    
    Token &Token::operator=(char c)
    {
    	if (tok == STR)
    		sval.~string();
    	cval = c;
    	tok = CHAR;
    	return *this;
    }
    
    Token &Token::operator=(const string &s)
    {
    	if (tok == STR)
    		sval = s;
    	else
    		new(&sval) string(s);
    	tok = STR;
    	return *this;
    }
    

      

    19.22

    class Token {
    public:
    	//其他见上题 
    	class Sales_data;
    }; 
    

      

    19.23

    	Token(Token &&t): tok(std::move(t.tok)) { moveUnion(std::move(t)); }
    	Token &operator=(Token &&t);
    

      

    19.24

    将一个Token对象赋给另一个Token对象:会运行拷贝赋值运算符,然后根据判别式的值来对相应的数据成员赋值。

    类似的,将一个Token对象赋给它自己的过程和上面的类似。

    19.25

    Token &Token::operator=(int i)
    {
    	if (tok == STR)
    		sval.~string();
    	ival = i;
    	tok = INT;
    	return *this;
    }
    
    Token &Token::operator=(double d)
    {
    	if (tok == STR)
    		sval.~string();
    	dval = d;
    	tok = DBL;
    	return *this;
    }
    
    Token &Token::operator=(char c)
    {
    	if (tok == STR)
    		sval.~string();
    	cval = c;
    	tok = CHAR;
    	return *this;
    }
    
    Token &Token::operator=(const string &s)
    {
    	if (tok == STR)
    		sval = s;
    	else
    		new(&sval) string(s);
    	tok = STR;
    	return *this;
    }
    

    补充:

    Token &Token::operator=(const Token &t)
    {
    	if (tok == STR && t.tok != STR)
    		sval.~string();
    	else if (tok == STR && t.tok == STR)
    		sval = t.sval;
    	else
    		copyUnion(t);		//内含各种类型的赋值 
    	tok = t.tok;
    	return *this;
    }
    
    void Token::copyUnion(const Token &t)
    {
    	switch (t.tok) {
    		case INT: 
    			ival = t.ival;
    			break;
    		case CHAR:
    			cval = t.cval;
    			break;
    		case DBL:
    			dval = t.dval;
    		case STR:
    			new(&sval) string(t.sval);
    			break;
    	}
    }
    

      

    19.26

    错误,C语言不支持函数重载

  • 相关阅读:
    (转)关于c#中的事件
    MySql数据库--持续记录ing
    在Eclipse中通过JDBC连接MySQL步骤,非常详细!
    mybatis传入参数类型parameterType和输出结果类型resultType详解
    关于JDBC访问存储过程的问题
    Mybatis(一)入门
    [Redis] 基于redis的分布式锁
    分布式锁----浅析redis实现
    MyBatis的增删改查操作
    C3P0连接池工具类实现步骤及方法
  • 原文地址:https://www.cnblogs.com/xzxl/p/7806162.html
Copyright © 2011-2022 走看看