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;
}

  

posted @ 2023-03-02 17:02  kangobs  阅读(12)  评论(0编辑  收藏  举报