C++Primer Plus笔记——第十五章 友元、异常和其他总结及程序清单

目录

本章小结

程序清单

友元类

15.1 tv.h                   15.2 tv.cpp                   15.3 use_tv.cpp            15.4 tvfm.h

嵌套类 

15.5 queuetp.h         15.6 nested.cpp

异常

15.7 error1.cpp          15.8 error2.cpp          15.9  error3.cpp            15.10 exc_mean.h

15.11 error4.cpp        15.12 error5.cpp        15.13 newexcp.cpp        15.14 sales.h

15.15 sales.cpp          15.16 usesales.cpp

运行阶段类型识别(RTTI)

15.17 rtti1.cpp              15.18 rtti2.cpp

类型转换运算符

15.19 constcast.cpp


本章小结

       友元使得能够为类开发更灵活的接口。类可以将其他函数、其他类和其他类的成员函数作为友元。在某些情况下,可能需要使用前向声明,需要特别注意类和方法声明的顺序,以正确地组合友元。

       嵌套类是在其他类中声明的类,它有助于设计这样的助手类,即实现其他类,但不必是公有接口的组成部分。

       C++异常机制为处理拙劣的编程事件,如不适当的值、I/O失败等。提供了一种灵活的方式。引发异常将终止当前执行的函数,将控制权传给匹配的catch块。catch块紧跟在try块的后面,为捕获异常,直接或间接导致异常的函数调用必须位于try块中。这样程序将执行catch块中的代码。这些代码试图解决问题或终止程。类可以包含嵌套的异常类,嵌套异常类在相应的问题被发现时将被引发。 函数可以包含异常规范,指出在该函数中可能引发的异常:但C++11摒弃了这项功能。未被捕获的异常(没有匹配的catch块的异常)在默认情况下将终止程序,意外异常(不与任何异常规范匹配的异常)也是如此。

       RTTI (运行阶段类型信息)特性让程序能够检测对象的类型。dynamic_cast运算符用于将派生类指针转换为基类指针,其主要用途是确保可以安全地调用虚函数。Typeid运算符返回一个type_info对象.可以 对两个typeid的返回值进行比较,以确定对象是否为特定的类型,而返回的type_info对象可用于获得关于对象的信息。

       与通用转换机制相比,dynamic_cast、static_cast、const_cast 和 reinterpret_cast 提供了更安全、更明确的类型转换.

程序清单

友元类

15.1 tv.h

// tv.h -- Tv and Remote classes
#ifndef TV_H_
#define TV_H_

class Tv
{
public:
	friend class Remote; // Remote can access Tv private parts
	enum { Off, On };
	enum { MinVal, MaxVal = 20 };
	enum { Antenna, Cable };
	enum { TV, DVD };
	Tv(int s = Off, int mc = 125) : state(s), volume(5),maxchannel(mc), channel(2), mode(Cable), input(TV) {}
	void onoff() {state = (state == On) ? Off : On; } 
	bool ison() const { return state == On; }
	bool volup(); 
	bool voldown();
	void chanup();
	void chandown();
	void set_mode() { mode = (mode == Antenna) ? Cable : Antenna; }
	void set_input() {input = ( input == TV) ? DVD : TV; } 
	void settings() const; // display all settings
private:
	int state;// on or off
	int volume; // assumed to be digitized
	int maxchannel;// maximum number of channels
	int channel; // current channel setting
	int mode; // broadcast or cable
	int input; // TV or DVD
};

class Remote	 
{
private:
	int mode;	// controls TV or DVD
public:
	Remote(int m = Tv::TV) : mode(m) {}
	bool volup(Tv & t) { return t.volup(); }
	bool voldown(Tv & t) { return t.voldown(); }
	void onoff(Tv & t) { t.onoff(); }
	void chanup(Tv & t) {t.chanup(); }
	void chandown(Tv & t) {t.chandown(); }
	void set_chan(Tv & t, int c) { t.channel = c; }
	void set_mode(Tv & t) { t.set_mode(); }
	void set_input(Tv & t) { t.set_input(); } 
};
#endif

15.2 tv.cpp

// tv.cpp -- methods for the Tv class (Remote methods are inline)
#include <iostream>
#include "tv.h"

bool Tv::volup()
{
	if (volume < MaxVal)
	{
		volume++; 
		return true;
	}
	else
		return false;
}

bool Tv::voldown()
{
	if (volume > MinVal)
	{
		volume--;
		return true;
	}
	else
		return false;
}

void Tv::chanup()
{
	if (channel < maxchannel) 
		channel++;
	else
		channel = 1;
}

void Tv::chandown()
{
	if (channel > 1)
		channel--;
	else
		channel = maxchannel;
}

void Tv::settings() const
{
	using std::cout;
	using std::endl;
	cout << "TV is " << (state == Off ? "Off" : "On") << endl;
	if (state == On)
	{
		cout << "Volume setting = " << volume << endl;
		cout << "Channel setting = " << channel << endl;
		cout << "Mode = " << (mode == Antenna ? "antenna" : "cable") << endl;
		cout << "Input = " << (input == TV ? "TV" : "DVD") << endl;
	}
}

15.3 use_tv.cpp

//use_tv.cpp -- using the Tv and Remote classes
#include <iostream> 
#include "tv.h"

int main()
{
	using std::cout;
	Tv s42;
	cout << "Initial settings for 42\" TV:\n";
	s42.settings();
	s42.onoff();
	s42.chanup();
	cout << "\nAdjusted settings for 42\" TV:\n";
	s42.chanup();
	cout << "\nAdjusted settings for 42\" TV:\n";
	s42.settings();

	Remote grey;

	grey.set_chan(s42, 10);
	grey.volup(s42);
	grey.volup(s42);
	cout << "\n42\" settings after using remote:\n";
	s42.settings();
	Tv s58(Tv::On);
	s58.set_mode();
	grey.set_chan(s58, 28);
	cout << "\nS8\" settings:\n";
	s58.settings();
	return 0;
}

15.4 tvfm.h

//tvfm.h -- Tv and Remote classes using a friend member
#ifndef TVFM_H_
#define TVFM_H_

class Tv;

class Remote
{
public:
	enum { Off, On };
	enum { MinVal, MaxVal = 20 };
	enum { Antenna, Cable };
	enum { TV, DVD };
	Remote(int m = TV) : mode(m) {}
	bool volup(Tv & t);
	bool voldown(Tv & t);
	void onoff(Tv & t);
	void chanup(Tv & t);
	void chandown(Tv & t);
	void set_mode(Tv & t);
	void set_input(Tv & t);
	void set_chan(Tv & t, int c);
private:
	int mode;
};

class Tv
{
public:
	friend void Remote::set_chan(Tv & t, int c);//just this function can access Tv private parts
	enum { Off, On };
	enum { MinVal, MaxVal = 20 };
	enum { Antenna, Cable };
	enum { TV, DVD };

	Tv(int s = Off, int mc = 125) : state(s), volume(5), maxchannel(mc), channel(2), mode(Cable), input(TV) {}
	void onoff() { state = (state == On) ? Off : On; }
	bool ison() const { return state == On; }
	bool volup();
	bool voldown();
	void chanup();
	void chandown();
	void set_mode() { mode = (mode == Antenna) ? Cable : Antenna; }
	void set_input() { input = (input == TV) ? DVD : TV; }
	void settings() const; // display all settings
private:
	int state;
	int volume;
	int maxchannel;
	int channel;
	int mode;
	int input;
};


// Remote methods as-inline functions
inline bool Remote::volup(Tv & t) { return t.volup(); } 
inline bool Remote::voldown(Tv & t) { return t.voldown(); } 
inline void Remote::onoff(Tv &t) { t.onoff(); } 
inline void Remote::chanup(Tv & t) {t.chanup();} 
inline void Remote::chandown(Tv & t) {t.chandown();} 
inline void Remote::set_mode(Tv & t) {t.set_mode();} 
inline void Remote::set_input(Tv & t) {t.set_input();} 
inline void Remote::set_chan(Tv & t, int c) { t.channel = c; }

#endif // !TVFM_H_

嵌套类

15.5 queuetp.h

// queuetp.h -- queue template with a nested class 
#ifndef QUEUETP_H_
#define QUEUETP_H_

template <class Item>

class QueueTP
{
private:
	enum { Q_SIZE = 10 };

	// Node is a nested class definition 
	class Node
	{
	public:
		Item item;
		Node * next;
		Node(const Item & i) :item(i), next(0) {}
	};

	Node * front; // pointer to front of Queue
	Node * rear; // pointer to rear of Queue
	int items; // current number of items in Queue
	const int qsize; // maximum number of items in Queue
	QueueTP(const QueueTP & q) : qsize(0) {}
	QueueTP & operator= (const QueueTP & q) { return *this; }
public:
	QueueTP(int qs = Q_SIZE);
	~QueueTP();
	bool isempty() const
	{
		return items == 0;
	}

	bool isfull() const
	{
	return items == qsize;
	}

	int queuecount() const
	{
		return items;
	}

	bool enqueue(const Item &item); // add item to end 
	bool dequeue(Item &item) ;	// remove item from front
};

// QueueTP methods
template <class Item>
QueueTP<Item>::QueueTP(int qs) : qsize(qs)
{
	front = rear = 0; 
	items = 0;
}

template <class Item>
QueueTP<Item> ::~QueueTP()
{
	Node * temp;
	while (front != 0)	// while queue is not yet empty
	{
		temp = front; // save address of front item 
		front = front->next;// reset pointer to next item 
		delete temp; // delete former front
	}
}

// Add item to queue
template <class Item>
bool QueueTP<Item>::enqueue(const Item & item)
{
	if (isfull())
		return false;
	Node * add = new Node(item); // create node // on failure, new throws std::bad_alloc exception 
	items++;
	if (front == 0)	// if queue is empty,
		front = add;	// place item at front
	else
		rear->next = add; // else place at rear
	rear = add;// have rear point to new node
	return true;
}


// Place front item into item variable and remove from queue 
template <class Item>
bool QueueTP<Item>::dequeue(Item & item)
{
	if (front == 0)
		return false; 
	item = front->item;// set item to first item in queue
	items--;
	Node * temp = front; // save location of first item 
	front = front -> next; // reset front to next item
	delete temp;  // delete former first item
	if (items == 0)
		rear = 0; 
	return true;
}
#endif

15.6 nested.cpp

// nested.cpp -- using a queue that has a nested class 
#include <iostream>
#include <string>
#include "queuetp.h"

int main()
{
	using std::string;
	using std::cin;
	using std::cout;

	QueueTP<string> cs(5);
	string temp;

	while (!cs.isfull())
	{
		cout << "Please enter your name. You will be served in the order of arrival.\nname: ";
		getline(cin, temp);
		cs.enqueue(temp);
	}
	cout << "The queue is full. Processing begins!\n";
	while (!cs.isempty())
	{
		cs.dequeue(temp);
		cout << "Now processing " << temp << "...\n";
	}
	return 0;
}

异常

15.7 error1.cpp

使用abort()函数

//error1.cpp -- using the abort() function
#include <iostream>
#include <cstdlib>

using namespace std;

double hmean(double a, double b);

int main()
{
	double x, y, z;

	cout << "Enter two numbers: "; 
	while (cin >> x >> y)
	{
		z = hmean(x, y);
		cout << "Harmonic mean of " << x << " and " << y << " is " << z << endl; 
		cout << "Enter next set of numbers <q to quit> : ";
	}
	cout << "Bye!\n"; 
	return 0;
}

double hmean(double a, double b)
{
	if (a == -b)
	{
		cout << "untenable arguments to hmeanU\n";
		abort();
	}
	return 2.0 * a * b / (a + b);
}

15.8 error2.cpp

返回错误码

//error2.cpp -- returning an error code 
#include <iostream>
#include <cfloat> // (or float.h) for DBL_MAX 

using namespace std;

bool hmean(double a, double b, double * ans);

int main()
{
	double x, y, z;
	cout << "Enter two numbers: ";
	while (cin >> x >> y)
	{
		if (hmean(x, y, &z))
			cout << "Harmonic mean of " << x << " and " << y << " is " << z << endl;
		else
			cout << "One value should not be the negative " << "of the other - try again.\n";
		cout << "Enter next set of numbers <q to quit>: ";
	}
	std::cout << "Bye!\n";
	return 0;
}

bool hmean(double a, double b, double * ans)
{
	if (a == -b)
	{
		*ans = DBL_MAX;
		return false;
	}
	else
	{
		*ans = 2.0 * a * b / (a + b);
		return true;
	}
}

15.9  error3.cpp

异常机制

//error3.cpp -- using an exception
#include <iostream>

using namespace std;

double hmean(double a, double b);

int main()
{
	double x, y, z;

	cout << "Enter two numbers: ";
	while (cin >> x >> y)
	{
		try//start of try block
		{
			z = hmean(x, y);
		}//end of try block
		catch (const char * s)//start of exception handler
		{
			cout << s << endl;
			cout << "Enter a new pair of numbers: ";
			continue;
		}//end of handler
		cout << "Harmonic mean of " << x << " and " << y << " is " << z << endl;
		cout << "Enter next set of numbers <q to quit> : ";
	}
	cout << "Bye!\n";
	return 0;
}

double hmean(double a, double b)
{
	if (a == -b)
		throw "bad hmean() arguments: a = -b not allowed";
	return 2.0 * a * b / (a + b);
}

15.10 exc_mean.h

将对象用作异常类型

// excmean.h -- exception classes for hmean(), gmean()
#include <iostream>

using namespace std;

class bad_hmean
{
private:
	double vl;
	double v2; 
public:
	bad_hmean(double a = 0, double b = 0) : vl(a), v2(b) {}
	void mesg();
};

inline void bad_hmean::mesg()
{
	cout << "hmean(" << vl << ", " << v2 << "): invalid arguments: a = -b\n";
}

class bad_gmean
{
public:
	double vl;
	double v2;
	bad_gmean(double a = 0, double b = 0) : vl(a), v2(b) {}
	const char * mesg();
};

inline const char * bad_gmean::mesg()
{
	return "gmean() arguments should b => 0\n";
}

15.11 error4.cpp

//error4.cpp - using exception classes
#include <iostream>
#include <cmath> 
#include "exc_mean.h"

using namespace std;

// function prototypes 
double hmean(double a, double b) ; 
double gmean(double a, double b);

int main()
{
	double x, y, z;
	cout << "Enter two numbers: ";
	while (cin >> x >> y)
	{
		try// start of try block
		{
			z = hmean(x, y);
			cout << "Harmonic mean of " << x << " and " << y << " is " << z << endl;
			cout << "Geometric mean of " << x << " and " << y << " is " << gmean(x, y) << endl;
			cout << "Enter next set of numbers <q to quit>: ";
		}// end of try block
		catch (bad_hmean & bg) // start of catch block
		{
			bg.mesg();
			cout << "Try again.\n";
			continue;
		}
		catch (bad_gmean & hg)
		{
			cout << hg.mesg();
			cout << "Values used: " << hg.vl << ", " << hg.v2 << endl;
			cout << "Sorry, you don't get to play any more.\n";
			break;
		} // end of catch block
	}
	cout << "Bye!\n";
	return 0;
}

double hmean(double a, double b)
{
	if (a == -b)
		throw bad_hmean(a, b); 
	return 2.0 * a * b / (a + b);
}

double gmean(double a, double b)
{
	if (a < 0 || b < 0)
		throw bad_gmean(a, b);
	return sqrt(a * b);
}

15.12 error5.cpp

栈解退

//error5.cpp -- unwinding the stack
#include <iostream>	
#include <cmath>
#include <string>
#include "exc_mean.h"

class demo
{
private:
	string word;
public:
	demo(const string & str)
	{
		word = str;
		std::cout << "demo " << word << " created\n";
	}
	~demo()
	{
		std::cout << "demo " << word << " destroyed\n";
	}
	void show() const
	{
		std::cout << "demo " << word << " lives!\n";
	}
};

// function prototypes
double hmean(double a, double b);
double gmean(double a, double b);
double means(double a, double b);

int main()
{
	using std::cout;
	using std::cin;
	using std::endl;

	double x, y, z;
	{
		demo d1("found in block in main() ");
		cout << "Enter two numbers : ";
		while (cin >> x >> y)
		{
			try// stare of try block
			{
				z = means(x, y);
				cout << "The mean mean of " << x << " and " << y << "is " << z << endl;
				cout << "Enter next pair: ";
			} // end of try block

			catch (bad_hmean & bg) // start of catch block
			{
				bg.mesg();
				cout << "Try again.\n";
				continue;
			}

			catch (bad_gmean & hg)
			{
				cout << hg.mesg();
				cout << "Values used: " << hg.vl << ", " << hg.v2 << endl;
				cout << "Sorry, you don't get to play any more.\n";
				break;
			} // end of catch block
		}
		d1.show();
	}
	cout << "Bye!\n";
	cin.get(); 
	cin.get(); 
	return 0;
}

double hmean(double a, double b)
{
	if (a == -b)
		throw bad_hmean(a, b);
	return 2.0 * a * b / (a + b);
}

double gmean(double a, double b)
{
	if (a < 0 || b < 0)
		throw bad_gmean(a, b); return std::sqrt(a * b);
}

double means(double a, double b)
{
	double am, hm, gm;
	demo d2("found in means{)");
	am = (a + b) / 2.0;	// arithmetic mean
	try
	{
		hm = hmean(a, b);
		gm = gmean(a, b);
	}
	catch (bad_hmean & bg) // start of catch block
	{
		bg.mesg();
		std::cout << "Caught in means()\n";
		throw;
	}
	d2.show();
	return (am + hm + gm) / 3.0;
}

15.13 newexcp.cpp

bad_alloc 异常和new

// newexcp.cpp -- the bad_alloc exception
#include <iostream>
#include <new>
#include <cstdlib> // for exitO, EXIT FAILURE 

using namespace std;

struct Big
{
	double stuff[20000];
};

int main()
{
	Big * pb;
	try
	{
		cout << "Trying to get a big block of memory:\n";
		pb = new Big[10000]; // 1,600,000,000 bytes
		cout << "Got past the new request:\n";
	}
	catch (bad_alloc & ba)
	{
		cout << "Caught the exception!\n";
		cout << ba.what() << endl;
		exit(EXIT_FAILURE);
	}
	cout << "Memory successfully allocated\n";
	pb[0].stuff[0] = 4;
	cout << pb[0].stuff[0] << endl;
	delete[] pb;
	return 0;
}

15.14 sales.h

异常、类和继承

// sales.h -- exceptions and inheritance 
#include <stdexcept>
#include <string>

class Sales
{
public:
	enum { MONTHS = 12 };	// could be a static const
	class bad_index : public std::logic_error
	{
	private:
		int bi; // bad index value 
	public:
		explicit bad_index(int ix, const std::string & s = "Index error in Sales object\n");
		int bi_val() const { return bi; }
		virtual ~bad_index() throw() {}
	};
	explicit Sales(int yy = 0);
	Sales(int yy, const double * gr, int n);
	virtual ~Sales() { }
	int Year() const { return year; }
	virtual double operator[](int i) const;
	virtual double & operator[](int i);
private:
	double gross[MONTHS];
	int year;
};

class LabeledSales : public Sales
{
public:
	class nbad_index : public Sales::bad_index
	{
	private:
		std::string lbl;
	public:
		nbad_index(const std::string & lb, int ix, const std::string & s = "Index error in LabeledSales object\n");
		const std::string & label_val() const { return lbl; }
		virtual ~nbad_index() throw() {}
	};
	explicit LabeledSales(const std::string & lb = "none", int yy = 0);
	LabeledSales(const std::string & lb, int yy, const double * gr, int n);
	virtual ~LabeledSales() {}
	const std::string & Label() const { return label; }
	virtual double operator[](int i) const;
	virtual double & operator[] (int i);
private:
	std::string label;
};

15.15 sales.cpp

// Sales.cpp -- Sales implementation
#include "sales.h" 
using std::string;

Sales::bad_index::bad_index(int ix, const string & s) : std::logic_error(s), bi(ix){}

Sales::Sales(int yy)
{
	year = yy;
	for (int i = 0; i < MONTHS; ++i)
		gross[i] = 0;
}

Sales::Sales(int yy, const double * gr, int n)
{
	year == yy;
	int lim = (n < MONTHS) ? n : MONTHS;
	int i;
	for (i = 0; i < lim; ++i)
		gross[i] = gr[i];
	// for i > n and i < MONTHS 
	for (; i < MONTHS; ++i)
		gross[i] = 0;
}

double Sales::operator[](int i) const
{
	if (i < 0 || i >= MONTHS)
		throw bad_index(i);
	return gross[i];
}

double & Sales::operator[](int i)
{
	if (i < 0 || i >= MONTHS)
		throw bad_index(i);
	return gross[i];
}

LabeledSales::nbad_index::nbad_index(const string & lb, int ix, const string & s) : Sales::bad_index(ix, s)
{
	lbl = lb;
}

LabeledSales::LabeledSales(const string & lb, int yy) : Sales(yy)
{
	label = lb;
}

LabeledSales::LabeledSales(const string & lb, int yy, const double * gr, int n) : Sales(yy, gr, n)
{
	label = lb;
}

double LabeledSales::operator[](int i) const
{
	if (i < 0 || i >= MONTHS)
		throw nbad_index(Label(), i);
	return Sales::operator [] (i);
}

double & LabeledSales::operator[] (int i)
{
	if (i < 0 || i >= MONTHS)
		throw nbad_index(Label(), i);
	return Sales::operator[](i);
}

15.16 usesales.cpp

// usesales.cpp -- nested exceptions 
#include <iostream> 
#include "sales.h"

int main()
{
	using std::cout;
	using std::cin;
	using std::endl;

	double vals1[12] =
	{
	1220, 1100, 1122, 2212, 1232, 2334,
	2864, 2393, 3302, 2922, 3002, 3544
	};

	double vals2[12] =
	{
		12, 11, 22, 21, 32, 34,
		28, 29, 33, 29, 32, 35,
	};
	Sales sales1(2011, vals1, 12);
	LabeledSales sales2("Blogstar", 2012, vals2, 12);

	cout << "First try block: \n";
	try
	{
		int i;
		cout << "Year = " << sales1.Year() << endl;
		for (i = 0; i < 12; ++i)
		{
			cout << sales1[i] << ' ';
			if (i % 6 == 5)
				cout << endl;
		}
		cout << "Year = " << sales2.Year() << endl;
		cout << "Label = " << sales2.Label() << endl;
		for (i = 0; i <= 12; ++i)
		{
			cout << sales2[i] << ' ';
			if (i % 6 == 5)
				cout << endl;
		}
		cout << "End of try block l.\n";
	}
	catch (LabeledSales::nbad_index & bad)
	{
		cout << bad.what();
		cout << "Company: " << bad.label_val() << endl;
		cout << "bad index: " << bad.bi_val() << endl;
	}
	catch (Sales::bad_index & bad)
	{
		cout << bad.what();
		cout << "bad index: " << bad.bi_val() << endl;
	}

	cout << "\nNext try block:\n";
	try
	{
		sales2[2] = 37.5;
		sales1[20] = 23345;
		cout << "End of try block 2.\n";
	}
	catch (LabeledSales::nbad_index & bad)
	{
		cout << bad.what();
		cout << "Company: " << bad.label_val() << endl;
		cout << "bad index : " << bad.bi_val() << endl;
	}
	catch (Sales::bad_index & bad)
	{
		cout << bad.what();
		cout << "bad index: " << bad.bi_val() << endl;
	}
	cout << "done\n";

	return 0;
}

运行阶段类型识别(RTTI)

15.17 rtti1.cpp

dynamic_cast运算符

//rttil.cpp -- using the RTTI dynamic_cast operator
#include <iostream>
#include <cstdlib>
#include <ctime>

using std::cout; 
class Grand
{
private:
	int hold;
public:
	Grand(int h = 0) : hold(h) {}
	virtual void Speak() const { cout << "I am a grand class h\n"; }
	virtual int Value() const { return hold; }
};

class Superb : public Grand
{
public:
	Superb(int h = 0) : Grand(h) {}
	void Speak() const { cout << "I am a superb class!!\n"; }
	virtual void Say() const
	{
		cout << "I hold the superb value of: " << Value() << "!\n";
	}
};

class Magnificent : public Superb
{
private:
	char ch;
public:
	Magnificent(int h = 0, char c = 'A') : Superb(h), ch(c) {}
	void Speak() const { cout << "I am a magnificent class I !!\n"; }
	void Say() const { cout << "I hold the character " << ch << " and the integer " << Value() << "!\n"; }
};

Grand * GetOne();

int main()
{

	std::srand(std::time(0));
	Grand * pg;
	Superb * ps;
	for (int i = 0; i < 5; i++)
	{
		pg - GetOne();
		pg->Speak();
		if (ps = dynamic_cast<Superb *>(pg))
			ps->Say();
	}
	return 0;
}

Grand * GetOne() // generate one of three kinds of objects randomly
{
		   Grand * p;
		   switch(std::rand() % 3)
		   {
		   case	0:	p = new Grand(std::rand()  % 100);
			   break;
		   case	1:	p = new Superb(std::rand() % 100);
			   break;
		   case	2:	p = new Magnificent(std::rand() % 100, 'A' + std::rand() % 26);
			   break;
		   }
return p;
}

15.18 rtti2.cpp

typeid运算符和type_info类

// rtti2.cpp -- using dynamic_cast, typeid, and type_info 
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <typeinfo> 

using namespace std;

class Grand
{
private:
	int hold;
public:
	Grand(int h = 0) : hold(h) {}
	virtual void Speak() const { cout << "I am a grand class!\n"; }
	virtual int Value() const { return hold; }
};

class Superb : public Grand
{
public:
	Superb( int h = 0) : Grand(h) {}
	void Speak() const { cout << "I am a superb class!!\n"; } 
	virtual void Say() const { cout << "I hold the superb value of " << Value() << "!\n"; }
};

class Magnificent : public Superb
{
private:
	char ch;
public:
	Magnificent(int h = 0, char cv = 'A') : Superb(h), ch(cv) {}
	void Speak() const { cout << "I am a magnificent class!!!\n"; }
	void Say() const { cout << "I hold the character " << ch << "and the integer " << Value() << "!\n"; }
};

Grand * GetOne();

int main()
{
	srand(time(0));
	Grand * pg;
	Superb * ps;
	for (int i = 0 ; i < 5; i++)
	{
	pg = GetOne();
	cout << "Now processing type " << typeid(*pg).name() << "\n"; 
	pg -> Speak(); 
	if (ps = dynamic_cast<Superb *>(pg))
		ps->Say();
	if (typeid(Magnificent) == typeid(*pg))
	cout << "Yes, you're really magnificent.\n";
	}
	return 0;
}

Grand * GetOne()
{
	Grand * p;

	switch (rand() % 3)
	{
	case 0: p = new Grand(rand() % 100);
		break;
	case 1: p = new Superb(rand() % 100);
		break;
	case 2: p = new Magnificent(rand() % 100, 'A' + rand() % 26);
		break;
	}
	return p;
}

类型转换运算符

15.19 constcast.cpp

使用const_cast运算符

// constcast.cpp -- using constcasto
#include <iostream>

using std::cout;
using std::endl;

void change(const int * pt, int n);

int main()
{
	int pop1 = 38383;
	const int pop2 = 2000;
	cout << "pop1, pop2: " << pop1 << ", " << pop2 << endl;
	change(&pop1, -103);
	change(&pop2, -103);
	cout << "pop1, pop2: " << pop1 << ", " << pop2 << endl;
	return 0;
}

void change(const int * pt, int n)
{
	int * pc;
	pc = const_cast<int *>(pt);
	*pc += n;
}

 

 

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值