以員工和經(jīng)理類為例,闡述繼承的關(guān)系
成員變量的覆蓋
猜猜下面的運行結(jié)果是什么呢?
#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <string>using std::string;// 繼承// 為什么要有繼承//    代碼的重用//        copy//        組合//            類,封裝//        繼承class Employee{public:    Employee(const string &name, const int lev, const int salary_base = 3000) :         name_(name), lev_(lev), salary_base_(salary_base)       // 構(gòu)造函數(shù)是不能被繼承下來的    {    }    int Salary()    {        return salary_base_ * lev_;    }PRotected:    string name_;    int no_;    int lev_;    int salary_base_;};class Manager : public Employee{public:    // 初始化列表中所初始化的變量是自己所擁有的的    // 也就是說在初始化之前是不用有父類中的成員變量的    Manager(const string &name, const int lev, const int salary_base = 5000) : Employee(name, lev, salary_base)    {    }    int Salary()    {        return static_cast<int>(salary_base_ * lev_ * 1.5);    }protected:    Employee *employees_;    int salary_base_;   // 這個變量是重定義,數(shù)據(jù)的重定義并非覆蓋};int main(){    Employee zs("張三", 10);    Manager ls("李四", 10);    std::cout << zs.Salary() << std::endl;    std::cout << ls.Salary() << std::endl;    return 0;}運行的結(jié)果是:  這個結(jié)果是不是令人匪夷所思呢?為什么經(jīng)理的工資是0呢? 那是因為經(jīng)理類中有兩個salary_base_的變量,在經(jīng)理類中只調(diào)用Employee類中的構(gòu)造函數(shù),只是給Employee類中的salary_base_變量賦值,并沒有給經(jīng)理類中的salary_base_變量賦值,所以才會出現(xiàn)經(jīng)理的工資是0的情況。改進(jìn)方法是給經(jīng)理類中的salary_base_變量也賦值。代碼如下所示:
 這個結(jié)果是不是令人匪夷所思呢?為什么經(jīng)理的工資是0呢? 那是因為經(jīng)理類中有兩個salary_base_的變量,在經(jīng)理類中只調(diào)用Employee類中的構(gòu)造函數(shù),只是給Employee類中的salary_base_變量賦值,并沒有給經(jīng)理類中的salary_base_變量賦值,所以才會出現(xiàn)經(jīng)理的工資是0的情況。改進(jìn)方法是給經(jīng)理類中的salary_base_變量也賦值。代碼如下所示:
#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <string>using std::string;// 繼承// 為什么要有繼承//    代碼的重用//        copy//        組合//            類,封裝//        繼承class Employee{public:    Employee(const string &name, const int lev, const int salary_base = 3000) :         name_(name), lev_(lev), salary_base_(salary_base)       // 構(gòu)造函數(shù)是不能被繼承下來的    {    }    int Salary()    {        return salary_base_ * lev_;    }protected:    string name_;    int no_;    int lev_;    int salary_base_;};class Manager : public Employee{public:    // 初始化列表中所初始化的變量是自己所擁有的的    // 也就是說在初始化之前是不用有父類中的成員變量的    Manager(const string &name, const int lev, const int salary_base = 5000) :         Employee(name, lev), salary_base_(salary_base), employees_(nullptr)    {    }    int Salary()    {        return static_cast<int>(salary_base_ * lev_ * 1.5);    }protected:    Employee *employees_;    int salary_base_;   // 這個變量是重定義,數(shù)據(jù)的重定義并非覆蓋,但是對于數(shù)據(jù)成員的重定義本身就是存在問題的};int main(){    Employee zs("張三", 10);    Manager ls("李四", 10);    std::cout << zs.Salary() << std::endl;    std::cout << ls.Salary() << std::endl;    return 0;} 所以,我們以后在管理成員變量的時候,各個類只需要(并且一定要)管理好自己本類中的成員變量即。
 所以,我們以后在管理成員變量的時候,各個類只需要(并且一定要)管理好自己本類中的成員變量即。
成員函數(shù)的覆蓋
當(dāng)經(jīng)理類中沒有實現(xiàn)Salary的函數(shù)時,那么經(jīng)理類對象調(diào)用的Salary函數(shù)將是Employee類中的Salary函數(shù),這樣經(jīng)理對象得到的工資肯定就會少了,代碼如下:
#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <string>using std::string;// 繼承// 為什么要有繼承//    代碼的重用//        copy//        組合//            類,封裝//        繼承class Employee{public:    Employee(const string &name, const int lev, const int salary_base = 3000) :         name_(name), lev_(lev), salary_base_(salary_base)       // 構(gòu)造函數(shù)是不能被繼承下來的    {    }    int Salary()    {        return salary_base_ * lev_;    }protected:    string name_;    int no_;    int lev_;    int salary_base_;};class Manager : public Employee{public:    // 初始化列表中所初始化的變量是自己所擁有的的    // 也就是說在初始化之前是不用有父類中的成員變量的    Manager(const string &name, const int lev, const int salary_base = 5000) :         Employee(name, lev), salary_base_(salary_base), employees_(nullptr)    {    }    //int Salary()    //{    //  return static_cast<int>(salary_base_ * lev_ * 1.5);    //}protected:    Employee *employees_;    int salary_base_;   // 這個變量是重定義,數(shù)據(jù)的重定義并非覆蓋};int main(){    Employee zs("張三", 10);    Manager ls("李四", 10);    std::cout << zs.Salary() << std::endl;    std::cout << ls.Salary() << std::endl;    return 0;}結(jié)果如下:  怎么會這樣呢?經(jīng)理的工資怎么和員工的工資一樣多了呢?經(jīng)理肯定會不高興的,不但不高興,肯定會不干的。 仔細(xì)看代碼不難發(fā)現(xiàn),經(jīng)理的工資的計算方式和員工的工資的計算方式是一樣的,所以得到的結(jié)果也是一樣的,這樣也太不公平了吧!!! 我們在經(jīng)理類中增加一個帶參數(shù)的Salary函數(shù),代碼如下所示:
 怎么會這樣呢?經(jīng)理的工資怎么和員工的工資一樣多了呢?經(jīng)理肯定會不高興的,不但不高興,肯定會不干的。 仔細(xì)看代碼不難發(fā)現(xiàn),經(jīng)理的工資的計算方式和員工的工資的計算方式是一樣的,所以得到的結(jié)果也是一樣的,這樣也太不公平了吧!!! 我們在經(jīng)理類中增加一個帶參數(shù)的Salary函數(shù),代碼如下所示:
#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <string>using std::string;// 繼承// 為什么要有繼承//    代碼的重用//        copy//        組合//            類,封裝//        繼承class Employee{public:    Employee(const string &name, const int lev, const int salary_base = 3000) :         name_(name), lev_(lev), salary_base_(salary_base)       // 構(gòu)造函數(shù)是不能被繼承下來的    {    }    int Salary()    {        return salary_base_ * lev_;    }protected:    string name_;    int no_;    int lev_;    int salary_base_;};class Manager : public Employee{public:    // 初始化列表中所初始化的變量是自己所擁有的的    // 也就是說在初始化之前是不用有父類中的成員變量的    Manager(const string &name, const int lev, const int salary_base = 5000) :         Employee(name, lev), salary_base_(salary_base), employees_(nullptr)    {    }        int Salary(double multiple) // 函數(shù)重定義,只要函數(shù)名相同就會構(gòu)成重定義,并且也不是覆蓋    {        return static_cast<int>(salary_base_ * lev_ * multiple);    }protected:    Employee *employees_;    int salary_base_;   // 這個變量是重定義,數(shù)據(jù)的重定義并非覆蓋};int main(){    Employee zs("張三", 10);    Manager ls("李四", 10);    std::cout << zs.Salary() << std::endl;    std::cout << ls.Salary() << std::endl;    return 0;}但是,此時編譯就會出問題,錯誤提示如下所示:  這是為什么呢?員工類中是有無參Salary的函數(shù)的呀!!!那為什么經(jīng)理類中就沒有這個函數(shù)了呢?因為Salary函數(shù)重定義,導(dǎo)致經(jīng)理類的對象無法直接使用員工類中的Salary函數(shù),但是也不是說經(jīng)理類把員工類中的Salary函數(shù)給覆蓋了。
 這是為什么呢?員工類中是有無參Salary的函數(shù)的呀!!!那為什么經(jīng)理類中就沒有這個函數(shù)了呢?因為Salary函數(shù)重定義,導(dǎo)致經(jīng)理類的對象無法直接使用員工類中的Salary函數(shù),但是也不是說經(jīng)理類把員工類中的Salary函數(shù)給覆蓋了。
#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <string>using std::string;// 繼承// 為什么要有繼承//    代碼的重用//        copy//        組合//            類,封裝//        繼承class Employee{public:    Employee(const string &name, const int lev, const int salary_base = 3000) :         name_(name), lev_(lev), salary_base_(salary_base)       // 構(gòu)造函數(shù)是不能被繼承下來的    {    }    int Salary()    {        return salary_base_ * lev_;    }protected:    string name_;    int no_;    int lev_;    int salary_base_;};class Manager : public Employee{public:    // 初始化列表中所初始化的變量是自己所擁有的的    // 也就是說在初始化之前是不用有父類中的成員變量的    Manager(const string &name, const int lev, const int salary_base = 5000) :         Employee(name, lev), salary_base_(salary_base), employees_(nullptr)    {    }    int Salary(double multiple) // 函數(shù)重定義,只要函數(shù)名相同就會構(gòu)成重定義,并且也不是覆蓋    {        return static_cast<int>(salary_base_ * lev_ * multiple);    }protected:    Employee *employees_;    int salary_base_;   // 這個變量是重定義,數(shù)據(jù)的重定義并非覆蓋};int main(){    Employee zs("張三", 10);    Manager ls("李四", 10);    std::cout << zs.Salary() << std::endl;    std::cout << ls.Employee::Salary() << std::endl;    //說明不是覆蓋,因為員工類中的Salary函數(shù)還是存在的    return 0;}關(guān)于組合和繼承關(guān)系的總結(jié)
#define _CRT_SECURE_NO_WARNINGS#include <iostream>#include <string>using std::string;// 繼承// 為什么要有繼承//    代碼的重用//        copy//        組合//            類,封裝//        繼承class Employee{public:    Employee(const string &name, const int lev, const int salary_base = 3000) :         name_(name), lev_(lev), salary_base_(salary_base)       // 構(gòu)造函數(shù)是不能被繼承下來的    {    }    int Salary()    {        return salary_base_ * lev_;    }protected:    string name_;    int no_;    int lev_;    int salary_base_;};class Manager : public Employee{public:    // 初始化列表中所初始化的變量是自己所擁有的的    // 也就是說在初始化之前是不用有父類中的成員變量的    Manager(const string &name, const int lev, const int salary_base = 5000) :         Employee(name, lev), salary_base_(salary_base), employees_(nullptr)    {    }    int Salary(double multiple) // 函數(shù)重定義,只要函數(shù)名相同就會構(gòu)成重定義,并且也不是覆蓋    {        return static_cast<int>(salary_base_ * lev_ * multiple);    }    // 我們大家都普遍會認(rèn)為繼承下來的函數(shù)會直接放在這個位置    // 比如員工類中的Salary函數(shù)放到這里,不就構(gòu)成重載了嗎?    // 那么為什么還不能直接調(diào)用無參的Salary函數(shù)呢?    // int Salary()    //  {    //      return salary_base_ * lev_;    //  }    //      // 顯然不是這樣的,我們有必要區(qū)分一下下面的概念    // 參數(shù)不同,能夠構(gòu)成重載                     overlord     重載          相同作用域    //   普通函數(shù)(只要函數(shù)名相同就會構(gòu)成重定義) overwrite     重寫,重定義  重定義的話,會默認(rèn)的使用離你近的    //  虛函數(shù)                                    override     覆蓋protected:    Employee *employees_;    int salary_base_;   // 這個變量是重定義,數(shù)據(jù)的重定義并非覆蓋};// 這個例子中的Employee類和C++標(biāo)準(zhǔn)庫中的string類是屬于組合關(guān)系// Manager類和Employee類是屬于繼承關(guān)系// 那么,無論是組合也好,還是繼承也好,這二者作用的結(jié)果是一樣的,// 都是將其他類直接放在本類中來使用,只是這二者的表達(dá)方式不一樣(設(shè)計模式)。// 組合關(guān)系一般是 has a 是通過嵌入的方式嵌入到本類中,更多的是希望你來幫我做事情,更多的是新類型暴露出來的一些接口// 比如Employee類,我們要是使用的話,會使用Employee暴露出來的方法,不會使用string類的方法,因為這兩個類已經(jīng)變成了// 以Employee類為主要功能的一個整體。使用has a來表現(xiàn)這種關(guān)系的話,說明我這個類是一個全新的類型,你應(yīng)該使用我的全新// 的類型進(jìn)行操作,我的全新的類型里面有一個string類型,它會來幫我完成一些功能,這是has a的關(guān)系所表達(dá)的意思// 繼承關(guān)系一般是 is a,新類和老類之間有一些相同的接口(功能),我們希望把這個功能繼承下來,變成子類型化,有可能會// 對繼承下來的功能進(jìn)行強化。int main(){    Employee zs("張三", 10);    Manager ls("李四", 10);    std::cout << zs.Salary() << std::endl;    std::cout << ls.Employee::Salary() << std::endl;    //說明不是覆蓋,因為員工類中的Salary函數(shù)還是存在的    return 0;}C++中的Operator=運算符是可以被繼承下來的
這個例子主要是想說明C++中的operator=函數(shù)是可以被繼承下來的,如果在派生類中重定義了operator=函數(shù),那么它就不會再調(diào)用基類中的operator=運算符了,如果沒有重定義operator=運算符,,它會被繼承下來的。
#define _CRT_SECURE_NO_WARNINGS#include <iostream>using std::string;class Employee{public:    Employee(const char *name, const int lev, const int salary_base = 3000) :         lev_(lev), salary_base_(salary_base)        // 構(gòu)造函數(shù)是不能被繼承下來的    {        std::size_t len = strlen(name);        name_ = new char[len + sizeof(char)];        strcpy(name_, name);    }    Employee &operator=(const Employee &other)    {        delete[] name_;        std::size_t len = strlen(other.name_);        name_ = new char[len + sizeof(char)];        strcpy(name_, other.name_);        lev_ = other.lev_;        salary_base_ = other.salary_base_;        return *this;    }    const char *GetName() const    {        return name_;    }    int Salary()    {        return salary_base_ * lev_;    }    int Salary(double multiple)    {        return static_cast<int>(salary_base_*lev_*multiple);    }protected:    char *name_;    int lev_;    int salary_base_;};class Manager : public Employee{public:    // 初始化列表中所初始化的變量是自己所擁有的的    // 也就是說在初始化之前是不用有父類中的成員變量的    Manager(const char *name, const int lev, const Employee *employee = nullptr, const int salary_base = 5000) :         Employee(name, lev), salary_base_(salary_base)    {        if (employee)        {            employees_ = new Employee("", 10);            //memcpy(employees_, employee, sizeof(Employee));            // 這樣的拷貝必然是一個淺拷貝,因為Employee類中有指針存在            employees_->operator=(*employee);        }    }    Manager &operator=(const Manager &other)    // 重定義    {        // 必須也要調(diào)用基類的operator=運算符        Employee::operator=(other);        if (!employees_)        {            employees_ = new Employee(*(other.employees_));        }        else        {            *employees_ = *(other.employees_);        }        return *this;    }    ~Manager()    {        delete employees_;    }    int Salary(double multiple) // 函數(shù)重定義,只要函數(shù)名相同就會構(gòu)成重定義,并且也不是覆蓋    {        return static_cast<int>(salary_base_ * lev_ * multiple);    }    Employee *employees_;protected:    int salary_base_;   // 這個變量是重定義,數(shù)據(jù)的重定義并非覆蓋};// 不能被繼承的函數(shù)// 構(gòu)造函數(shù) 析構(gòu)函數(shù)int main(){    Employee *zs = new Employee("張三", 10);    Manager *ls = new Manager("李四", 10);    Manager *ww = new Manager("王五", 12, zs);    *ls = *ww; // 只調(diào)用了子類的operator=運算符    delete zs;    delete ww;    std::cout << ls->employees_->GetName() << std::endl;    std::cout << ls->GetName() << std::endl;    //std::cout << zs.Salary() << std::endl;    std::cout << ls->Employee::Salary(1.5) << std::endl;    //說明不是覆蓋,因為員工類中的Salary函數(shù)還是存在的    return 0;}拷貝構(gòu)造函數(shù)可以被派生類繼承
#define _CRT_SECURE_NO_WARNINGS#include <iostream>using std::string;class Employee{public:    Employee(const char *name, const int lev, const int salary_base = 3000) :         lev_(lev), salary_base_(salary_base)        // 構(gòu)造函數(shù)是不能被繼承下來的    {        std::size_t len = strlen(name);        name_ = new char[len + sizeof(char)];        strcpy(name_, name);    }    Employee(const Employee &other)    {        std::size_t len = strlen(other.name_);        name_ = new char[len + sizeof(char)];        strcpy(name_, other.name_);        lev_ = other.lev_;        salary_base_ = other.salary_base_;    }    Employee &operator=(const Employee &other)    {        delete[] name_;        std::size_t len = strlen(other.name_);        name_ = new char[len + sizeof(char)];        strcpy(name_, other.name_);        lev_ = other.lev_;        salary_base_ = other.salary_base_;        return *this;    }    const char *GetName() const    {        return name_;    }    int Salary()    {        return salary_base_ * lev_;    }    int Salary(double multiple)    {        return static_cast<int>(salary_base_*lev_*multiple);    }protected:    char *name_;    int lev_;    int salary_base_;};class Manager : public Employee{public:    // 初始化列表中所初始化的變量是自己所擁有的的    // 也就是說在初始化之前是不用有父類中的成員變量的    Manager(const char *name, const int lev, const Employee *employee = nullptr, const int salary_base = 5000) :         Employee(name, lev), salary_base_(salary_base)    {        if (employee)        {            employees_ = new Employee("", 10);            //memcpy(employees_, employee, sizeof(Employee));            // 這樣的拷貝必然是一個淺拷貝,因為Employee類中有指針存在            employees_->operator=(*employee);        }    }    Manager &operator=(const Manager &other)    // 重定義    {        // 必須也要調(diào)用基類的operator=運算符        Employee::operator=(other);        if (!employees_)        {            employees_ = new Employee(*(other.employees_));        }        else        {            *employees_ = *(other.employees_);        }        return *this;    }    ~Manager()    {        delete employees_;    }    int Salary(double multiple) // 函數(shù)重定義,只要函數(shù)名相同就會構(gòu)成重定義,并且也不是覆蓋    {        return static_cast<int>(salary_base_ * lev_ * multiple);    }    Employee *employees_;protected:    int salary_base_;   // 這個變量是重定義,數(shù)據(jù)的重定義并非覆蓋};// 不能被繼承的函數(shù)// 構(gòu)造函數(shù) 析構(gòu)函數(shù)int main(){    Employee *zs = new Employee("張三", 10);    Manager *ls = new Manager("李四", 10);    Manager ww = *ls;    //Manager *ww = new Manager("王五", 12, zs);    //*ls = *ww; // 只調(diào)用了子類的operator=運算符    //delete zs;    //delete ww;    //std::cout << ls->employees_->GetName() << std::endl;    //    //std::cout << ls->GetName() << std::endl;    ////std::cout << zs.Salary() << std::endl;    //std::cout << ls->Employee::Salary(1.5) << std::endl;  //說明不是覆蓋,因為員工類中的Salary函數(shù)還是存在的    return 0;}公有繼承的類是is a的關(guān)系,可以向上轉(zhuǎn)換,其余的protected和private方式繼承的就不是is a的關(guān)系了,也就不能向上轉(zhuǎn)換了
#define _CRT_SECURE_NO_WARNINGS#include <iostream>using std::string;class Employee{public:    Employee(const char *name, const int lev, const int salary_base = 3000) :         lev_(lev), salary_base_(salary_base)        // 構(gòu)造函數(shù)是不能被繼承下來的    {        std::size_t len = strlen(name);        name_ = new char[len + sizeof(char)];        strcpy(name_, name);    }    Employee(const Employee &other)    {        std::size_t len = strlen(other.name_);        name_ = new char[len + sizeof(char)];        strcpy(name_, other.name_);        lev_ = other.lev_;        salary_base_ = other.salary_base_;    }    Employee &operator=(const Employee &other)    {        delete[] name_;        std::size_t len = strlen(other.name_);        name_ = new char[len + sizeof(char)];        strcpy(name_, other.name_);        lev_ = other.lev_;        salary_base_ = other.salary_base_;        return *this;    }    const char *GetName() const    {        return name_;    }    int Salary()    {        return salary_base_ * lev_;    }    int Salary(double multiple)    {        return static_cast<int>(salary_base_*lev_*multiple);    }protected:    char *name_;    int lev_;    int salary_base_;};class Manager : public Employee{public:    // 初始化列表中所初始化的變量是自己所擁有的的    // 也就是說在初始化之前是不用有父類中的成員變量的    Manager(const char *name, const int lev, const Employee *employee = nullptr, const int salary_base = 5000) :         Employee(name, lev), salary_base_(salary_base)    {        if (employee)        {            employees_ = new Employee("", 10);            //memcpy(employees_, employee, sizeof(Employee));            // 這樣的拷貝必然是一個淺拷貝,因為Employee類中有指針存在            employees_->operator=(*employee);        }    }    // 雖然說已經(jīng)繼承下來了基類中的拷貝構(gòu)造函數(shù),但是我們還是需要重寫派生類中的拷貝構(gòu)造函數(shù)    // 因為基類中的拷貝構(gòu)造函數(shù)對于派生類來說構(gòu)造的不是很完整    // 并且我們必須在初始化列表中顯示的去調(diào)用基類中的拷貝構(gòu)造函數(shù),那么這樣的話,如果派生類    // 中寫了拷貝構(gòu)造函數(shù),那么基類中就必須有拷貝構(gòu)造函數(shù),否則派生類中是無法重定義拷貝構(gòu)造函數(shù)的    // 需要注意的是,為什么派生類的對象能夠直接當(dāng)成基類的對象來使用呢?    // 這是因為公有繼承的 is a 的關(guān)系,如果不是以public方式繼承的時候,此時就不是is a的關(guān)系了    Manager(const Manager &other) : Employee(other)    {        if (!other.employees_)        {            employees_ = new Employee(*(other.employees_));        }    }    Manager &operator=(const Manager &other)    // 重定義    {        // 必須也要調(diào)用基類的operator=運算符        Employee::operator=(other);        if (!employees_)        {            employees_ = new Employee(*(other.employees_));        }        else        {            *employees_ = *(other.employees_);        }        return *this;    }    ~Manager()    {        delete employees_;    }    int Salary(double multiple) // 函數(shù)重定義,只要函數(shù)名相同就會構(gòu)成重定義,并且也不是覆蓋    {        return static_cast<int>(salary_base_ * lev_ * multiple);    }    Employee *employees_;protected:    int salary_base_;   // 這個變量是重定義,數(shù)據(jù)的重定義并非覆蓋};// 不能被繼承的函數(shù)// 構(gòu)造函數(shù) 析構(gòu)函數(shù)int main(){    Employee *zs = new Employee("張三", 10);    Manager *ls = new Manager("李四", 10);    Manager ww = *ls;    //Manager *ww = new Manager("王五", 12, zs);    //*ls = *ww; // 只調(diào)用了子類的operator=運算符    //delete zs;    //delete ww;    //std::cout << ls->employees_->GetName() << std::endl;    //    //std::cout << ls->GetName() << std::endl;    ////std::cout << zs.Salary() << std::endl;    //std::cout << ls->Employee::Salary(1.5) << std::endl;  //說明不是覆蓋,因為員工類中的Salary函數(shù)還是存在的    return 0;}另一個簡單的例子來說明原因 public的繼承方式
#define _CRT_SECURE_NO_WARNINGS#include <iostream>class A{};class B : public A{};int main(){    B b;    A a = b; // 此時可以直接將派生類的對象轉(zhuǎn)換為基類的對象    A c;    c = b;    return 0;}#define _CRT_SECURE_NO_WARNINGS#include <iostream>class A{};class B : public A{public:    int b_;};int main(){    A *pa = new A;    B *pb = new B;    A a;    B b;    pa = pb;    // 派生類向基類轉(zhuǎn)換,就會產(chǎn)生對象切割(丟失特性)    pa->b_;     // 此時就無法訪問b_了,這就叫做丟失特性    pb = pa;    // 基類不可以向基類轉(zhuǎn)化    a = b;    b = a;    return 0;}剩下的protected和private繼承就無法轉(zhuǎn)化了。讀者可以自行試驗。 但是我們可以使用強制轉(zhuǎn)換,但是這是很危險的一件事情,最好不要這樣做。
#define _CRT_SECURE_NO_WARNINGS#include <iostream>class A{};class B : public A{public:    int b_;};int main(){    A *pa = new A;    B *pb = new B;    A a;    B b;    pa = pb;    // 派生類向基類轉(zhuǎn)換,就會產(chǎn)生對象切割(丟失特性)    pa->b_;     // 此時就無法訪問b_了,這就叫做丟失特性    pb = pa;    // 基類不可以向基類轉(zhuǎn)化    a = b;    b = a;    static_cast //做的是編譯器認(rèn)可的轉(zhuǎn)化    reinterpret_cast //做的是編譯器不認(rèn)可的轉(zhuǎn)換,是二進(jìn)制直接轉(zhuǎn)換的        // 指針可以用它來轉(zhuǎn)換,但是對象無論如何都轉(zhuǎn)換不了的    return 0;}不能被繼承下來的函數(shù)只有構(gòu)造函數(shù)和析構(gòu)函數(shù)
這里我們就不再舉例子了