C++入門(9):類的繼承(2)

C++入門(9):類的繼承(2)

構造器越簡明越好,最好只用它來初始化各有關屬性。
訪問控制通過訪問級別實現:
1)public : 任何代碼都可以訪問;
2)protected : 這個類本身和它的子類可以訪問;
3)private : 只有這個類本身可以訪問;

對函數/方法進行重載一定要慎重,重載方法/函數越多,程序就越不容易看懂;
覆蓋方法
在對方法進行覆蓋(注意不是重載)時一定要認真仔細;只要聲明的輸入參數和返回值與原來的不一致,則編寫出來的方法就將是一個重載方法而不是一個覆蓋方法。

友元關係
友元關係是類(函數)之間的一種特殊關係,這種關係允許友元訪問對方的所有方法和屬性;
聲明一個友元關係:只要在類聲明裏的某個地方加上一條 friend class MyFriend; 語句就可以了;
我們應該只在沒有其他辦法時才使用友元關係,挑選友元的時候一定要謹慎。

下面通過舉例詳細講解類繼承中的問題:

#include <iostream>
#include <string>

class Pet{                                            //基類
    public:
        Pet(std::string theName) ;                    //構造函數
        ~Pet() ;

        void eat();
        void sleep();
        void play();                                  //覆蓋方法
    protected:
        std::string name;

    friend class PetRenamer;                          //聲明友元關係
};

/*子類繼承基類時,如果使用了protected保留字,則把基類的訪問級別改爲protected--如果它們原來是public的話,這將使得這個子類外部的代碼無法通過這個子類去訪問其基類中的public元素。
如果使用了private保留字,則從基類繼承來的每一個成員都當做它是用private保留字聲明的情況來對待,即只有這個子類可以使用它從基類繼承來的元素。*/

class Dog : public Pet{                               //繼承時使用public保留字,則繼承的方法和屬性的訪問級別不發生任何改變
    public:
        Dog(std::string theName);
        ~Dog();
        void bark();
        void play();
};

class Cat : public Pet{
    public:
        Cat(std::string theName) ;
        ~Cat();
        void climb();
        void play();
};

class PetRenamer{                                     //與Pet類是友元關係的類
    public:
        PetRenamer(std::string theName);
        void rename(Pet *pet, std::string newName);

    private:
        std::string name;
};

PetRenamer::PetRenamer(std::string theName)
{
    name = theName;
}
void PetRenamer::rename(Pet *pet, std::string newName)
{
    std::cout << this->name << " is going to rename " << pet->name << " to " << newName << std::endl;
    pet->name = newName;
}

Pet::Pet(std::string theName)                         //定義構造器的時候,如果有默認參數,不用寫出其初始化值 !!
{
    std::cout << "I am Pet's Constructor." << std::endl;
    name = theName;
    std::cout << name << std::endl;
}
Pet::~Pet()
{
    std::cout << "I am Pet's Destructor." << std::endl;
}
void Pet::eat()
{
    std::cout << "This " << name << " is eating... " << std::endl;
}
void Pet::sleep()
{
    std::cout << "This " << name << " is sleeping..." << std::endl;
}
void Pet::play()
{
    std::cout << "The pet is playing..." << std::endl;
}

Dog::Dog(std::string theName):Pet(theName)           //語法含義:當調用Dog()時(以theName作爲輸入參數),Pet()也將被調用(theName輸入參數也會傳遞給它),賦值動作將實際發生在Pet()方法裏
{
    std::cout << "I am Dog's Constructor." << std::endl;
    std::cout << name << std::endl;
}
Dog::~Dog()
{
    std::cout << "I am Dog's Destructor." << std::endl;
}
void Dog::bark()
{
    std::cout << "This " << name << " is barking..." << std::endl;
}
void Dog::play()                                    //覆蓋基類中的play()方法
{
    Pet::play();                                    //可以調用基類方法
    std::cout << "The dog is playing" << std::endl;
}

Cat::Cat(std::string theName):Pet(theName)
{
    std::cout << "I am Cat's Constructor." << std::endl;
    std::cout << name << std::endl;
}
Cat::~Cat()
{
    std::cout << "I am Cat's Destructor." << std::endl;
}
void Cat::climb()
{
    std::cout << "This " << name << " is climbing..." << std::endl;
}
void Cat::play()
{
    Pet::play();                                      //調用基類方法
    std::cout << "The cat is playing" << std::endl;
}

int main(int argc, char** argv) {

    Pet pet("pet");
    Dog dog("dog");                                   //先調用一次Pet的構造器,再調用一次Dog的構造器
    Cat cat("cat");                                   //先調用一次Pet的構造器,再調用一次Cat的構造器
    PetRenamer petRenamer("Jessica");

    dog.eat();
    dog.bark();
    cat.climb();
    pet.sleep() ;
    pet.play();
    dog.play() ;
    cat.play();

    std::cout << std::endl;

    petRenamer.rename(&pet, "pet111") ;
    pet.eat();
    petRenamer.rename(&dog, "dog111") ;
    dog.eat() ;

    //程序結束時,依次調用類的析構器
    return 0;
}

運行結果爲:

I am Pet's Constructor.
pet
I am Pet's Constructor.
dog
I am Dog's Constructor.
dog
I am Pet's Constructor.
cat
I am Cat's Constructor.
cat
This dog is eating...
This dog is barking...
This cat is climbing...
This pet is sleeping...
The pet is playing...
The pet is playing...
The dog is playing
The pet is playing...
The cat is playing

Jessica is going to rename pet to pet111
This pet111 is eating...
Jessica is going to rename dog to dog111
This dog111 is eating...
I am Cat's Destructor.
I am Pet's Destructor.
I am Dog's Destructor.
I am Pet's Destructor.
I am Pet's Destructor.

C++入門(8):類的繼承(1)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章