C++ Primer中级(续)
14.转换操作符
转换函数
operator int() const;
注意:
1.必须是成员函数
2.不能指定返回类型
3.形参表必须是空的
4.必须显式地返回一个指定类型的值
5.不应该改变被转换对象,通常定义为const
#include <iostream>
#include <string>
using namespace std;
class Dog
{
public:
Dog(string n,int a,double w):name(n),
age(a),weight(w)
{
}
operator int() const
{
return age;
}
private:
int age;
double weight;
string name;
};
int main()
{
int a,b;
a=10;
b=a;
Dog d("Bill",6,15.0);
b = d;
cout<<b<<endl;
return 0;
}
15.定义基类和派生类
基类
virtual函数
protected成员
派生类
类派生列表
重定义virtual函数
可以访问基类的public和protected成员
16.动态绑定
多态性
从派生类到基类的转换
引用或指针既可以指向基类对象,也可以指向派生类对象
只有通过引用或指针调用虚函数才会发生动态绑定
#include <iostream>
#include <string>
using namespace std;
class Animal
{
};
class Dog:public Animal
{
};
class Cat:public Animal
{
};
class Item_base
{
public:
int x;
Item_base(const string &book="",double sales_price=0.0):
isbn(book),price(sales_price){}
string book() const
{
return isbn;
}
virtual double net_price(size_t n) const
{
return n*price;
}//虚函数可以在继承以后重新定义
private:
string isbn;
protected:
double price;
};
class Bulk_item:public Item_base
{
public:
Bulk_item(const string &book="",double sales_price=0.0,
size_t qty=0,double disc_rate=0.0):Item_base(book,sales_price),
min_qty(qty),discount(disc_rate)
{
}
void test()
{
cout<<x<<endl;
cout<<price<<endl;
//cout<<isbn<<endl;
}
void test2(const Bulk_item&d ,const Item_base&b)
{
cout<<d.price<<endl;
//cout<<b.price<<endl;
}
double net_price(size_t cnt) const
{
if(cnt>=min_qty)
return cnt*(1-discount)*price;
else
return cnt*price;
}
private:
size_t min_qty;
double discount;
};
void print_total(ostream& os,Item_base* item,size_t n)
{
os<<"ISBN:"<<item->book()<<"\t number: "<<n<<"\t total price: "<<item->net_price(n)<<endl;
}
int main()
{
Item_base* a = new Item_base("1-234-567-01",11.0);
Bulk_item* b = new Bulk_item("1-234-567-02",22.0,2,0.05);
//Bulk_item* c = new Item_base("1-234-567-01",11.0);
print_total(cout,a,2);
print_total(cout,b,3);
//print_total(cout,c,2);
Item_base* books[5];
books[0] = new Item_base("0-123-456-01",10.0);
books[1] = new Bulk_item("0-123-456-02",20.0,6,0.05);
books[2] = new Item_base("0-123-456-03",30.0);
books[3] = new Bulk_item("0-123-456-04",40.0,4,0.15);
books[4] = new Bulk_item("0-123-456-05",50.0,2,0.18);
int num[5];
num[0] = 2;
num[1] = 10;
num[2] = 1;
num[3] = 5;
num[4] = 3;
for(int i=0;i<5;++i)
{
print_total(cout,books[i],num[i]);
}
return 0;
}
17.三种继承
公有、私有、受保护继承
接口继承和实现继承
修改继承访问(去除个别成员)
默认继承访问级别
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class A
{
public:
int a;
A()
{
a=10;
b=20;
c=30;
}
void test()
{
cout<<c<<endl;
}
protected:
int b;
private:
int c;
};
class B1:public A
{
public:
void test()
{
cout<<a<<endl;
cout<<b<<endl;
//cout<<c<<endl;
}
};
class C:public B1
{
public:
void test()
{
cout<<a<<endl;
cout<<b<<endl;
//cout<<c<<endl;
}
};
class B2:private A
{
public:
using A::a;
void test()
{
cout<<a<<endl;
cout<<b<<endl;
}
};
class B4:A//默认是private
{
};
int main()
{
B1 b1;
cout<<b1.a<<endl;
//cout<<b1.b<<endl;
b1.test();
//cout<<b1.b<<endl;
//cout<<b1.c<<endl;
B2 b2;
cout<<b2.a<<endl;
return 0;
}
18.派生类的构造函数和析构函数
派生类的构造函数
执行基类的构造函数
执行成员对象的构造函数
执行派生类的构造函数
派生类的析构函数
对派生类新增普通成员进行清理
调用成员对象析构函数
调用基类析构函数
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Base1
{
public:
Base1(int i)
{
b1 = i;
cout<<"Base1的构造函数"<<endl;
}
void Print() const
{
cout<<b1<<endl;
}
private:
int b1;
};
class Base2
{
public:
Base2(int i)
{
b2 = i;
cout<<"Base2的构造函数"<<endl;
}
void Print() const
{
cout<<b2<<endl;
}
private:
int b2;
};
class Base3
{
public:
Base3()
{
b3 = 0;
cout<<"Base3的缺省构造函数"<<endl;
}
void Print() const
{
cout<<b3<<endl;
}
private:
int b3;
};
class Member
{
public:
Member(int i)
{
m=i;
cout<<"Member的构造函数被调用"<<endl;
}
int GetM()
{
return m;
}
private:
int m;
};
class Derived:public Base1,public Base2,public Base3
{
public:
Derived(int i,int j,int k,int l);
void Print();
private:
int d;
Member mem;
};
Derived::Derived(int i,int j,int k,int l):Base1(i),Base2(j),mem(k)
{
d=l;
cout<<"派生类的构造函数被调用"<<endl;
}
void Derived::Print()
{
Base1::Print();
Base2::Print();
Base3::Print();
cout<<mem.GetM()<<endl;
cout<<d<<endl;
}
int main()
{
Derived obj(1,2,3,4);
obj.Print();
return 0;
}
19.转换与继承
派生类到基类
引用转换
指针转换
对象转换
基类到转换类
基类到派生类的自动转换不存在
强制转换
Bulk_item *p = static_cast<Bulk_item *>(&item)
20.友元与继承
友元可以访问类的private和protected成员
友元关系不能继承
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Base //你爸爸
{
friend class Frnd;
friend class D2;
protected:
int i;
};
class D1:public Base//你
{
friend class Frnd;
friend class D2;
protected:
int j;
};
class Frnd//我爸爸
{
public:
int mem(Base b) {return b.i;}
int mem(D1 d){return d.j;}
};
class D2:public Frnd//我
{
public:
int mem(Base b){return b.i;}
int mem(D1 d){return d.j;}
};
int main()
{
Base a;
D1 b;
Frnd c;
D2 d;
return 0;
}
21.静态成员与继承
基类中的static成员,在整个继承层次中只有一个实例
在派生类中访问static成员的方法
1.基类名::成员名
2.子类名::成员名
3.对象.成员名
4.指针->成员名
5.成员名
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class A
{
public:
static size_t object_count()
{
return 100;
}
protected:
static const size_t obj_count=99;
};
class B:public A
{
public:
void f(const B &b,B *b2)
{
//b.obj_count = 101;
//A::obj_count = 99;
cout<<A::obj_count<<endl;
cout<<B::obj_count<<endl;
cout<<b.obj_count<<endl;
cout<<obj_count<<endl;
cout<<b2->obj_count<<endl;
cout<<endl;
cout<<A::object_count()<<endl;
cout<<B::object_count()<<endl;
cout<<b.object_count()<<endl;
cout<<object_count()<<endl;
cout<<b2->object_count()<<endl;
}
};
class C:public B
{
public:
void f1()
{
cout<<object_count()<<endl;
}
};
int main()
{
B b;
b.f(b,&b);
C c;
c.f(b,&b);
return 0;
}
22.纯虚函数与抽象类
纯虚函数
抽象类 - 抽象数据类型
任何包含一个或多个纯虚函数的类都是抽象类
不要创建这个类的对象,应该继承它
务必覆盖从这个类继承的纯虚函数
实现纯虚函数
C++接口
就是只包含纯虚函数的抽象基类
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Shape
{
public:
Shape(){}
virtual ~Shape(){}
//virtual double GetArea() = 0;
virtual double GetPerim() = 0;
virtual void Draw() = 0;
virtual void Speak(){cout<<"Test"<<endl;}
};
class Circle:public Shape{
public:
Circle(int radius):itsRadius(radius){}
virtual ~Circle(){}
double GetArea(){return 3.14*itsRadius*itsRadius;}
double GetPerim(){return 2*3.14*itsRadius;}
void Draw();
private:
int itsRadius;
};
void Circle::Draw()
{
cout<<"Circle drawing routine here!"<<endl;
}
class Rectangle:public Shape
{
public:
Rectangle(int len,int width):itsLength(len),itsWidth(width){}
virtual ~Rectangle(){}
double GetArea(){return itsLength*itsWidth;}
double GetPerim() {return 2*itsLength+2*itsWidth;}
virtual int GetLength() {return itsLength;}
virtual int GetWidth() {return itsWidth;}
void Draw();
private:
int itsWidth;
int itsLength;
};
void Rectangle::Draw()
{
for(int i=0;i<itsLength;++i)
{
for(int j=0;j<itsWidth;++j)
cout<<"x ";
cout<<endl;
}
}
class Square :public Rectangle
{
};
int main()
{
Circle a(10);
a.Draw();
Rectangle b(10,5);
b.Draw();
b.Speak();
return 0;
}
23.模板与泛型编程
两种模板
类模板、函数模板
泛型编程
主要用于容器、迭代器、算法 -> C++ STL 标准模板库
示例
1.普通队列
2.C++中的泛型队列
3.顺序队列
4.链式队列
24.函数模板
函数模板 -> 实例化 ->函数
模板形参
template <typename T>
template <class T>
四个例子
#include<iostream>
#include <string>
#include <fstream>
#include <sstream>
using namespace std;
/*
int compare(const double &v1,const double &v2)
{
if(v1<v2) return -1;
if(v1>v2) return 1;
if(v1==v2) return 0;
}
*/
template<typename T>
int compare(const T& v1,const T& v2)
{
if(v1<v2) return -1;
if(v1>v2) return 1;
if(v1==v2) return 0;
}
template<class T>
T absVal(T val)
{
return val>0?val:-val;
}
template<typename T1,typename T2>
T1& print(T1& s,T2 val)
{
s<<val;
return s;
}
int main()
{
double d1=1.2,d2=2.2;
cout<<compare(d1,d2)<<endl;
string s1="hi",s2="hello";
cout<<compare(s1,s2)<<endl;
double dval=-0.88;
float fval = -12.3;
string oristr = "this is a test";
string desstr;
ostringstream oss(desstr);
ofstream outFile("result.dat");
print(cout,-3)<<endl;
print(cout,oristr)<<endl;
print(outFile,-3)<<endl;
outFile.close();
print(oss,-3)<<endl;
cout<<absVal(dval)<<endl;
cout<<absVal(fval)<<endl;
return 0;
}
24.智能指针、auto_ptr类
常规指针 - 容易产生内存泄漏
智能指针
使用std::auto_ptr智能指针
使用Boost智能指针
使用ATL框架中的智能指针如CComPtr、CComQIPtr等等
#include <iostream>
#include <memory>
using namespace std;
void demo2()
{
auto_ptr<double> pd(new double);
*pd = 28.5;
cout<<*pd<<endl;
}
void demo1()
{
double d;
d = 25.5;
double *pd = new double;
*pd = 25.5;
cout<<d<<endl;
cout<<*pd<<endl;
delete pd;
return;
}
int main()
{
demo1();
demo2();
return 0;
}
25.命名空间
命名空间的定义
每个命名空间是一个作用域
命名空间可以是不连续的
接口和实现的分离
嵌套命名空间
命名空间成员的使用
using std::vector
using primer = cplusplus_primer
using namespace std;
26.多继承与虚基类
多继承
多继承中的二义性问题
虚基类(解决菱形继承)
虚基类的构造函数
#include <iostream>
using namespace std;
enum COLOR {Red,Green,Blue,Yellow,White,Black,Brown};
class Animal
{
public:
Animal(int);
virtual ~Animal() {cout<<"Animal系噶偶"<<endl;}
virtual int GetAge() {return itsAge;}
virtual void SetAge(int age){itsAge = age;}
private:
int itsAge;
};
Animal::Animal(int age):itsAge(age)
{
cout<<"Animal构造函数"<<endl;
}
class Horse:virtual public Animal
{
public:
Horse(COLOR color,int height,int age);
virtual ~Horse(){cout<<"Horse析构函数被调用"<<endl;};
virtual void Whinny() const {cout<<"Whinny!..."<<endl;}
virtual int GetHeight() const {return itsHeight;}
virtual COLOR GetColor() const {return itsColor;}
private:
int itsHeight;
COLOR itsColor;
};
Horse::Horse(COLOR color,int height,int age):itsHeight(height),itsColor(color),Animal(age)
{
cout<<"Horse构造函数被调用"<<endl;
}
class Bird:virtual public Animal
{
public:
Bird(COLOR color,bool migrates,int age);
virtual ~Bird(){cout<<"Bird析构函数被调用"<<endl;}
virtual void Chrip() const {cout<<"Chirp"<<endl;}
virtual void Fly() const {
cout<<"I can fly!"<<endl;
}
virtual bool GetMigration() const {return itsMigration;}
virtual COLOR GetColor() const {return itsColor;}
private:
bool itsMigration;
COLOR itsColor;
};
Bird::Bird(COLOR color,bool migrates,int age):itsMigration(migrates),itsColor(color),Animal(age)
{
cout<<"Bird构造函数被调用"<<endl;
}
class Pegasus:public Horse,public Bird
{
public:
Pegasus(COLOR,int,bool,long,int);
~Pegasus(){cout<<"Pegasus析构函数被调用"<<endl;}
void Chrip() const { Whinny();}
virtual long GetNumberBelievers() const
{
return itsNumberBelievers;
}
private:
long itsNumberBelievers;
};
Pegasus::Pegasus(COLOR aColor,int height,bool migrates,long numBelieve,int age):
Horse(aColor,height,age),
Bird(aColor,migrates,age),
itsNumberBelievers(numBelieve),
Animal(age)
{
cout<<"Pegasus构造函数被调用"<<endl;
}
int main()
{
Pegasus *pPeg = new Pegasus(Red,5,true,10,100);
//char *p = new char [5];
//char *p1 = new char('s');
pPeg->Fly();
pPeg->Whinny();
pPeg->Chrip();
cout<<pPeg->Horse::GetColor()<<endl;
cout<<pPeg->Bird::GetColor()<<endl;
cout<<"有"<<pPeg->GetNumberBelievers()<<"相信"<<endl;
cout<<pPeg->GetAge()<<endl;
delete pPeg;
return 0;
}
27.特殊工具与技术
allocator类
RTTI
类成员的指针
嵌套类
union
局部类
位域
volatile
extern ”C“
#include <iostream>
#include <string>
using namespace std;
class Item_base
{
public:
virtual double net_price(size_t n) const
{
return n*price;
}
public:
string isbn;
protected:
double price;
};
class Bulk_item: public Item_base
{
public:
double net_price(size_t cnt) const
{
if (cnt>min_qty)
return cnt*(1-discount)*price;
else
return cnt*price;
}
private:
size_t min_qty;
double discount;
};
union TokenValue
{
char cval;
int ival;
double dval;
};
typedef unsigned int Bit;
class File{
public:
Bit mode: 2;
Bit modified: 1;
Bit prot_owner: 3;
Bit prot_group: 3;
Bit prot_world: 3;
};
extern "C" void show(char *);
int main()
{
show("hello extern \"C\"\n");
TokenValue myToken = {'a'};
cout<<myToken.ival<<endl;
Item_base *pItem = new Item_base();
allocator<Item_base> a;
a.allocate(100);
Item_base *bp = new Item_base();
Bulk_item *dp = new Bulk_item();
Item_base *bp2 = dp;
Bulk_item *dp2 = dynamic_cast<Bulk_item*> (bp);//动态类型转换 RRTI 运行时类型识别
if(typeid(Bulk_item) == typeid(*dp))
cout<<"Bulk_item类型"<<endl;
cout<<typeid(*bp).name()<<endl;
//类成员指针
string Item_base::* p = &Item_base::isbn;
double (Item_base::*pmf)(size_t) const = &Item_base::net_price;
return 0;
}

浙公网安备 33010602011771号