【足迹C++primer】54、继承类的范围,构造函数和拷贝控制

继承类的范围,构造函数和拷贝控制

当用派生类执行函数的时候,首先会在当前的类里面找
如果找不到就一级一级地往上找。


Name Lookup Happens at Compile Time

class Quote
{
public:
    Quote()=default;
    Quote(const string &book, double sales_price):bookNo(book), price(sales_price)
     {cout<<"Quote gouzhao function"<<endl;}
    string isbn() const {return bookNo;}
    //返回指定数量的项目总销售价格
    //派生类将重写应用不同的折扣算法
    virtual double net_price(size_t n) const {return n*price;}
    virtual ~Quote()=default;   //动态链接析构函数
private:
    string bookNo;  //这本书的isbn号
protected:
    double price=0.0;       //不打折的价格

};

class Bulk_quote : public Quote
{
public:
    Bulk_quote()=default;
    Bulk_quote(const string & book, double p, size_t qty, double disc)
    : Quote(book, p), min_qty(qty), discount(disc)
    {cout<<"Bulk_quote construct function"<<endl;}
    //重写虚函数
    double net_price(size_t n) const override {cout<<"double net_price(size_t)"<<endl; return n*price;}
    //再次说明,请声明函数后一定要记得定义它,不然我这是出了各种莫名其妙的错误!
//    ~Bulk_quote2(){cout<<"~Bulk_quote2()"<<endl;}
    ///--------------------------------
    pair<size_t, double> discount_policy() const {return {min_qty, discount};}
private:
    size_t min_qty=0;
    double discount=0.0;
};


class Disc_quote : public Quote
{
public:
    Disc_quote()=default;
    Disc_quote(const string & book, double price, size_t qty, double disc):
        Quote(book, price), quantity(qty), discount(disc) {cout<<"Disc_quote构造函数"<<endl;}
    double net_price(size_t) const = 0; //纯虚函数
    ///-------------------------------------------------
    pair<size_t, double> discount_policy() const {return {quantity, discount};}
protected:
    size_t quantity=0;
    double discount=0.0;
};


void fun1()
{
    Bulk_quote bulk;
    Bulk_quote *bulkP=&bulk;
    Quote *itemP=&bulk;
    bulkP->discount_policy();   //好的这是一个指针类似(*bulkP).discount_policy()
//    item->discount_policy();  error:Quote里面没有这个成员

}

Name Collisions and Inheritance(名字冲突的时候继承)

struct Base
{
    Base():mem(0) {}
protected:
    int mem;
};

struct Derived : Base
{
    Derived(int i) : mem(i) {}  //这里初始化的是Derived的mem用i,而Base::mem是默认初始化的
    int get_mem() { return mem; }   //返回Derived::mem
protected:
    int mem;    //吧base的mem隐藏起来
};

void fun2()
{
    Derived d(42);
    cout<<d.get_mem()<<endl;    //输出42
}

使用作用域操作符使用隐藏的成员

除了重写继承的虚函数的派生类,通常
不应使用基类中定义的名字。

As Usual, Name Lookup Happens before Type Checking

struct Base2
{
    Base2():mem(0) {}
    int memfcn() {}
protected:
    int mem;
};

struct Derived2 : Base2
{
    Derived2()=default;
    Derived2(int i) : mem(i) {}  //这里初始化的是Derived的mem用i,而Base::mem是默认初始化的
    int get_mem() { return mem; }   //返回Derived::mem
    int memfcn(int) {}    //吧Base2中的memfcn隐藏了
protected:
    int mem;    //吧base的mem隐藏起来
};

void fun3()
{
    Derived2 d;
    Base2 b;
    b.memfcn(); //----->Base的Base::memfcn()
    d.memfcn(10);   //----->Derived的Derived::memfcn()
//    d.memfcn();     error:这个Derived里面继承Base里面的memfcn被隐藏了
    d.Base2::memfcn();   //ok:调用Base::memfcn
}

Virtual Functions and Scope
class Base3
{
public:
    virtual int fcn() {cout<<"Base3--->virtual int fcn()"<<endl;}
};

class D1 : public Base3
{
public:
    int fcn(int){cout<<"D1--->int fcn(int)"<<endl;}   //这个是隐藏了fcn不叫override
    virtual void f2(){cout<<"D1--->virtual void f2()"<<endl;}
};

class D2 : public D1
{
public:
    int fcn(int){cout<<"D2--->int fcn(int)"<<endl;}  //这个是隐藏,没有override在D1这个不是虚函数
    int fcn(){cout<<"D2--->int fcn()"<<endl;}      //是覆盖,override
    void f2(){cout<<"D2--->void f2()"<<endl;}      //覆盖,virtual f2 from D1
};

void fun4()
{
    Base3 b3obj; D1 d1obj; D2 d2obj;
    Base3 *b3p1=&b3obj, *b3p2=&d1obj, *b3p3=&d2obj;
    b3p1->fcn();    //这个调用了Base3::fcn
    b3p2->fcn();    //调用Base3::fcn
    b3p3->fcn();    //调用D2::fcn

    D1 *d1p=&d1obj; D2 *d2p=&d2obj;
//    b3p2->f2();   error:Base没有f2!!注意是Base而不是D1,因为*b3p2的类型是Base多余部分没有拷贝
    d1p->f2();  //D1--->virtual void f2()
    d2p->f2();  //D2--->void f2()

    Base3 *p1=&d2obj;   D1 *p2=&d2obj;  D2 *p3=&d2obj;
//    p1->fcn(42);      error:Base3没有fcn(int)函数
    p2->fcn(42);    //D1--->int fcn(int)
    p3->fcn(42);    //D2--->int fcn(int)
}

构造函数和拷贝控制

Virtual Destructors(虚析构函数)

void fun5()
{
    Quote *itemP=new Quote;
    delete itemP;
    itemP=new Bulk_quote;
    delete itemP;
}

15.7.2. Synthesized Copy Control and Inheritance

Base Classes and Deleted Copy Control in the Derived

class B
{
public:
    B(){cout<<"B()构造函数"<<endl;}
    B(const B&)=delete; //这个函数的意思是,这个类不能调用这个函数,默认的都不行
};

class D : public B
{
    //什么都没有!!!
};

void fun6()
{
    D d;
//    D d2(d);   error:这个会默认调用了B的B(const B&)但是这个是delete了的
//    D d3(std::move(d));   error:同上
}

Move Operations and Inheritance(移动操作与继承)

哎!大家一定要学好英语啊,我是以前不能长期坚持搞得现在英语真是“阴雨”
用的翻译软件,╮(╯▽╰)╭翻译的什么玩意,有的我自己都看不懂,读不通


class Quote2
{
public:
    Quote2()=default;   //默认构造函数
    Quote2(const string &book, double sales_price):bookNo(book), price(sales_price)
     {cout<<"Quote gouzhao function"<<endl;}
    //拷贝函数
    Quote2(const Quote2&)=default;
    Quote2(Quote2&&)=default;
    //拷贝赋值运算符,和移动赋值运算符
    Quote2& operator=(const Quote2&)=default;
    Quote2& operator=(Quote2&&)=default;
    //析构函数
    virtual ~Quote2()=default;   //动态链接析构函数

    string isbn() const {return bookNo;}
    //返回指定数量的项目总销售价格
    //派生类将重写应用不同的折扣算法
    virtual double net_price(size_t n) const {return n*price;}

private:
    string bookNo;  //这本书的isbn号
protected:
    double price=0.0;       //不打折的价格

};

15.7.3. Derived-Class Copy-Control Members

派生类拷贝控制成员

当派生类定义了一个复制或移动操作,那么这个操作符将负责整个类的相应操作
还包括基类的成员的相应操作

定义一个派生拷贝或移动构造函数

默认情况下,基类的默认构造函数初始化基类部分
派生的对象。如果我们想要复制(或移动)基类部分,我们必须
显式使用复制(或移动)在对基类构造函数
派生的构造函数初始化列表。

这里我就不给大家定义了,书上给的很泛,没什么意义

class Base { /* ... */ } ;
class D: public Base {
public:
// by default, the base class default constructor initializes the base part of an object
// to use the copy or move constructor, we must explicitly call that
// constructor in the constructor initializer list
D(const D& d): Base(d) // copy the base members
{ /* ... */ }//initializers for members of D
D(D&& d): Base(std::move(d)) // move the base members
/* initializers for members of D / { /* ... */ }
};

// Base::operator=(const Base&) is not invoked automatically
D &D::operator=(const D &rhs)
{
Base::operator=(rhs); // assigns the base part
// assign the members in the derived class, as usual,
// handling self-assignment and freeing existing resources as appropriate
return *this;
}

class D: public Base {
public:
// Base::~Base invoked automatically
~D() { /* do what it takes to clean up derived members / }
};

析构基类会自动进行!!!但是{}里面的清理对象还是都要写,基类已经写delete了的就
会自动调用基类析构函数时调用!!

15.7.4.继承析构函数

在新标准下,一个派生类可以调用基类的构造函数

class Bulk_quote2 : public Disc_quote
{
public:
    using Disc_quote::Disc_quote;
    //构造函数等价于
    /*
    Bulk_quote(const string & book, double price, size_t qty, double disc)
    : Disc_quote(book, price, qty, disc){}
    */
    double net_price(size_t n) const {cout<<"Bulk_quote2,net_price"<<endl; return n*price;}
};

继承构造函数的特点

好吧书上一堆“阴雨”!!!~~~~


the all code !! 

/**
* 功能:继承类的范围,构造函数和拷贝控制
* 时间:2014年7月22日07:53:20
* 作者:cutter_point
*/

#include<iostream>
#include<algorithm>

using namespace std;

/*
当用派生类执行函数的时候,首先会在当前的类里面找
如果找不到就一级一级地往上找。
*/

/**
Name Lookup Happens at Compile Time
*/

class Quote
{
public:
    Quote()=default;
    Quote(const string &book, double sales_price):bookNo(book), price(sales_price)
     {cout<<"Quote gouzhao function"<<endl;}
    string isbn() const {return bookNo;}
    //返回指定数量的项目总销售价格
    //派生类将重写应用不同的折扣算法
    virtual double net_price(size_t n) const {return n*price;}
    virtual ~Quote()=default;   //动态链接析构函数
private:
    string bookNo;  //这本书的isbn号
protected:
    double price=0.0;       //不打折的价格

};

class Bulk_quote : public Quote
{
public:
    Bulk_quote()=default;
    Bulk_quote(const string & book, double p, size_t qty, double disc)
    : Quote(book, p), min_qty(qty), discount(disc)
    {cout<<"Bulk_quote construct function"<<endl;}
    //重写虚函数
    double net_price(size_t n) const override {cout<<"double net_price(size_t)"<<endl; return n*price;}
    //再次说明,请声明函数后一定要记得定义它,不然我这是出了各种莫名其妙的错误!
//    ~Bulk_quote2(){cout<<"~Bulk_quote2()"<<endl;}
    ///--------------------------------
    pair<size_t, double> discount_policy() const {return {min_qty, discount};}
private:
    size_t min_qty=0;
    double discount=0.0;
};


class Disc_quote : public Quote
{
public:
    Disc_quote()=default;
    Disc_quote(const string & book, double price, size_t qty, double disc):
        Quote(book, price), quantity(qty), discount(disc) {cout<<"Disc_quote构造函数"<<endl;}
    double net_price(size_t) const = 0; //纯虚函数
    ///-------------------------------------------------
    pair<size_t, double> discount_policy() const {return {quantity, discount};}
protected:
    size_t quantity=0;
    double discount=0.0;
};


void fun1()
{
    Bulk_quote bulk;
    Bulk_quote *bulkP=&bulk;
    Quote *itemP=&bulk;
    bulkP->discount_policy();   //好的这是一个指针类似(*bulkP).discount_policy()
//    item->discount_policy();  error:Quote里面没有这个成员

}

/**
Name Collisions and Inheritance(名字冲突的时候继承)
*/
struct Base
{
    Base():mem(0) {}
protected:
    int mem;
};

struct Derived : Base
{
    Derived(int i) : mem(i) {}  //这里初始化的是Derived的mem用i,而Base::mem是默认初始化的
    int get_mem() { return mem; }   //返回Derived::mem
protected:
    int mem;    //吧base的mem隐藏起来
};

void fun2()
{
    Derived d(42);
    cout<<d.get_mem()<<endl;    //输出42
}

/**
使用作用域操作符使用隐藏的成员
*/

/*
除了重写继承的虚函数的派生类,通常
不应使用基类中定义的名字。
*/

/**
As Usual, Name Lookup Happens before Type Checking
*/
struct Base2
{
    Base2():mem(0) {}
    int memfcn() {}
protected:
    int mem;
};

struct Derived2 : Base2
{
    Derived2()=default;
    Derived2(int i) : mem(i) {}  //这里初始化的是Derived的mem用i,而Base::mem是默认初始化的
    int get_mem() { return mem; }   //返回Derived::mem
    int memfcn(int) {}    //吧Base2中的memfcn隐藏了
protected:
    int mem;    //吧base的mem隐藏起来
};

void fun3()
{
    Derived2 d;
    Base2 b;
    b.memfcn(); //----->Base的Base::memfcn()
    d.memfcn(10);   //----->Derived的Derived::memfcn()
//    d.memfcn();     error:这个Derived里面继承Base里面的memfcn被隐藏了
    d.Base2::memfcn();   //ok:调用Base::memfcn
}

/**
Virtual Functions and Scope
*/
class Base3
{
public:
    virtual int fcn() {cout<<"Base3--->virtual int fcn()"<<endl;}
};

class D1 : public Base3
{
public:
    int fcn(int){cout<<"D1--->int fcn(int)"<<endl;}   //这个是隐藏了fcn不叫override
    virtual void f2(){cout<<"D1--->virtual void f2()"<<endl;}
};

class D2 : public D1
{
public:
    int fcn(int){cout<<"D2--->int fcn(int)"<<endl;}  //这个是隐藏,没有override在D1这个不是虚函数
    int fcn(){cout<<"D2--->int fcn()"<<endl;}      //是覆盖,override
    void f2(){cout<<"D2--->void f2()"<<endl;}      //覆盖,virtual f2 from D1
};

void fun4()
{
    Base3 b3obj; D1 d1obj; D2 d2obj;
    Base3 *b3p1=&b3obj, *b3p2=&d1obj, *b3p3=&d2obj;
    b3p1->fcn();    //这个调用了Base3::fcn
    b3p2->fcn();    //调用Base3::fcn
    b3p3->fcn();    //调用D2::fcn

    D1 *d1p=&d1obj; D2 *d2p=&d2obj;
//    b3p2->f2();   error:Base没有f2!!注意是Base而不是D1,因为*b3p2的类型是Base多余部分没有拷贝
    d1p->f2();  //D1--->virtual void f2()
    d2p->f2();  //D2--->void f2()

    Base3 *p1=&d2obj;   D1 *p2=&d2obj;  D2 *p3=&d2obj;
//    p1->fcn(42);      error:Base3没有fcn(int)函数
    p2->fcn(42);    //D1--->int fcn(int)
    p3->fcn(42);    //D2--->int fcn(int)
}

/**************************************
构造函数和拷贝控制
**************************************/

/**
Virtual Destructors(虚析构函数)
*/
void fun5()
{
    Quote *itemP=new Quote;
    delete itemP;
    itemP=new Bulk_quote;
    delete itemP;
}

/**************************************
15.7.2. Synthesized Copy Control and Inheritance
**************************************/

/**
Base Classes and Deleted Copy Control in the Derived
*/
class B
{
public:
    B(){cout<<"B()构造函数"<<endl;}
    B(const B&)=delete; //这个函数的意思是,这个类不能调用这个函数,默认的都不行
};

class D : public B
{
    //什么都没有!!!
};

void fun6()
{
    D d;
//    D d2(d);   error:这个会默认调用了B的B(const B&)但是这个是delete了的
//    D d3(std::move(d));   error:同上
}

/**
Move Operations and Inheritance(移动操作与继承)
*/

/*
哎!大家一定要学好英语啊,我是以前不能长期坚持搞得现在英语真是“阴雨”
用的翻译软件,╮(╯▽╰)╭翻译的什么玩意,有的我自己都看不懂,读不通
*/
class Quote2
{
public:
    Quote2()=default;   //默认构造函数
    Quote2(const string &book, double sales_price):bookNo(book), price(sales_price)
     {cout<<"Quote gouzhao function"<<endl;}
    //拷贝函数
    Quote2(const Quote2&)=default;
    Quote2(Quote2&&)=default;
    //拷贝赋值运算符,和移动赋值运算符
    Quote2& operator=(const Quote2&)=default;
    Quote2& operator=(Quote2&&)=default;
    //析构函数
    virtual ~Quote2()=default;   //动态链接析构函数

    string isbn() const {return bookNo;}
    //返回指定数量的项目总销售价格
    //派生类将重写应用不同的折扣算法
    virtual double net_price(size_t n) const {return n*price;}

private:
    string bookNo;  //这本书的isbn号
protected:
    double price=0.0;       //不打折的价格

};

/**************************************
15.7.3. Derived-Class Copy-Control Members
派生类拷贝控制成员
**************************************/

/*
当派生类定义了一个复制或移动操作,那么这个操作符将负责整个类的相应操作
还包括基类的成员的相应操作
*/

/**
定义一个派生拷贝或移动构造函数
*/

/*
默认情况下,基类的默认构造函数初始化基类部分
派生的对象。如果我们想要复制(或移动)基类部分,我们必须
显式使用复制(或移动)在对基类构造函数
派生的构造函数初始化列表。
*/

/*
这里我就不给大家定义了,书上给的很泛,没什么意义
*/
class Base { /* ... */ } ;
class D: public Base {
public:
// by default, the base class default constructor initializes the base part of an object
// to use the copy or move constructor, we must explicitly call that
// constructor in the constructor initializer list
D(const D& d): Base(d) // copy the base members
{ /* ... */ }//initializers for members of D
D(D&& d): Base(std::move(d)) // move the base members
/* initializers for members of D / { /* ... */ }
};

// Base::operator=(const Base&) is not invoked automatically
D &D::operator=(const D &rhs)
{
Base::operator=(rhs); // assigns the base part
// assign the members in the derived class, as usual,
// handling self-assignment and freeing existing resources as appropriate
return *this;
}

class D: public Base {
public:
// Base::~Base invoked automatically
~D() { /* do what it takes to clean up derived members / }
};

析构基类会自动进行!!!但是{}里面的清理对象还是都要写,基类已经写delete了的就
会自动调用基类析构函数时调用!!
*/

/**************************************
15.7.4.继承析构函数
**************************************/
/*
在新标准下,一个派生类可以调用基类的构造函数
*/
class Bulk_quote2 : public Disc_quote
{
public:
    using Disc_quote::Disc_quote;
    //构造函数等价于
    /*
    Bulk_quote(const string & book, double price, size_t qty, double disc)
    : Disc_quote(book, price, qty, disc){}
    */
    double net_price(size_t n) const {cout<<"Bulk_quote2,net_price"<<endl; return n*price;}
};

/**
继承构造函数的特点
*/

/*
好吧书上一堆“阴雨”!!!
*/



int main()
{
    cout<<">>------------------------------fun1-----------------------------------<<"<<endl;
    cout<<">>------------------------------fun2-----------------------------------<<"<<endl;
    fun2();
    cout<<">>------------------------------fun3-----------------------------------<<"<<endl;
    cout<<">>------------------------------fun4-----------------------------------<<"<<endl;
    fun4();
    cout<<">>------------------------------fun5-----------------------------------<<"<<endl;
    fun5();
    cout<<">>------------------------------fun6-----------------------------------<<"<<endl;
    fun6();

    system("pause");
    return 0;
}





茶,冷了,苦涩了。喝茶果然还是热点好,香味十足,甘甜完美。冷淡下来了,就只有火热的回忆,和苦涩的冰凉!






【足迹C++primer】54、继承类的范围,构造函数和拷贝控制,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。