《21天学通C++》(第十章)实现继承(1)

1.派生语法

语法如下:

class Base{

};

class Name:access-specifier Base{
			//access-specifier可以是public、private、protect

};

一个简单的继承结构程序:

#include <iostream> 
using namespace std; 

// 定义一个基类Fish
class Fish {
public:
    bool isFreshWaterFish; // 一个布尔型成员变量,表示鱼是淡水鱼还是咸水鱼

    // 一个虚函数Swim,根据鱼的种类输出不同的游泳场所
    void Swim() {
        if (isFreshWaterFish) {
            cout << "swim in lake" << endl; // 如果是淡水鱼,输出在湖中游泳
        } else {
            cout << "swim in sea" << endl; // 如果是咸水鱼,输出在海中游泳
        }
    }
};

// 定义一个派生类Tuna,继承自Fish
class Tuna : public Fish {
public:
    Tuna() {
        isFreshWaterFish = false; // 将isFreshWaterFish设置为false,表示Tuna是咸水鱼
    }
};

// 定义另一个派生类Carp,同样继承自Fish
class Carp : public Fish {
public:
    Carp() {
        isFreshWaterFish = true; // 将isFreshWaterFish设置为true,表示Carp是淡水鱼
    }
};


int main() {
    Carp lunch; // 创建一个Carp类型的对象lunch
    Tuna dinner; // 创建一个Tuna类型的对象dinner

    cout << "lunch: " << endl; // 输出午餐的描述
    lunch.Swim(); // 调用lunch的Swim函数

    cout << "dinner: " << endl; // 输出晚餐的描述
    dinner.Swim(); // 调用dinner的Swim函数

    system("pause"); 
    return 0;
}

2.访问限定符protected

将属性声明为protected时,允许友元类和派生类访问该属性,但禁止在继承结构之外访问

示例代码如下

class Fish
{
protected://声明为protected
    bool isFreshWaterFish;
publicvoid Swim(){
        if (isFreshWaterFish)
        {
            cout<<"swim in lake"<<endl;
        }
        else{
            cout<<"swim in sea"<<endl;
        }        
    }
};

3.基类初始化

如果基类包含重载的构造函数,可以使用初始化列表传递参数
示例代码如下:

#include <iostream> 
using namespace std; 

// 定义基类Fish
class Fish {
protected:
    bool isFreshWaterFish; // 一个受保护的布尔型成员变量,表示鱼是淡水鱼还是咸水鱼
    Fish(bool isFreshWater) : isFreshWaterFish(isFreshWater) {}
    // 构造函数,根据传入的参数初始化isFreshWaterFish
public:

    // 一个虚函数Swim,根据鱼的种类输出不同的游泳场所
    void Swim() {
        if (isFreshWaterFish) {
            cout << "swim in lake" << endl; // 如果是淡水鱼,输出在湖中游泳
        } else {
            cout << "swim in sea" << endl; // 如果是咸水鱼,输出在海中游泳
        }
    }
};

// 定义派生类Tuna,继承自Fish
class Tuna : public Fish {
public:
    // Tuna的构造函数,使用Fish的构造函数并传入false,表示Tuna是咸水鱼
    Tuna() : Fish(false) {}
};

// 定义另一个派生类Carp,同样继承自Fish
class Carp : public Fish {
public:
    // Carp的构造函数,使用Fish的构造函数并传入true,表示Carp是淡水鱼
    Carp() : Fish(true) {}
};


int main() {
    Carp lunch; // 创建一个Carp类型的对象lunch
    Tuna dinner; // 创建一个Tuna类型的对象dinner

    cout << "lunch: " << endl; // 输出午餐的描述
    lunch.Swim(); // 调用lunch的Swim函数

    cout << "dinner: " << endl; // 输出晚餐的描述
    dinner.Swim(); // 调用dinner的Swim函数

    system("pause");
    return 0; 
}

这样可以强迫在构造一个派生类时,必须定义一个这样的函数来为其赋值,避免不定义的情况下,随机数值产生影响

4.在派生类中覆盖基类方法

只要派生类中实现了从基类中继承的函数,且返回值和标值相同,就可以覆盖

class Fish
{
protected:
    bool isFreshWaterFish;
    Fish(bool isFreshWater):isFreshWaterFish(isFreshWater){};

public:

    void Swim(){
        if (isFreshWaterFish)
        {
            cout<<"swim in lake"<<endl;
        }
        else{
            cout<<"swim in sea"<<endl;
        }        
    }
};

class Tuna:public Fish{
public:
    Tuna():Fish(false){};
     void Swim(){//覆盖基类中的方法
        cout<<"fu gai"<<endl;
     }

};

5.调用基类中已经被覆盖的方法

使用作用域解析运算符::

Dinner.Fish::Swim();//调用基类中的方法
Dinner.Swim();//调用覆盖后的方法

6.在派生类中的覆盖方法中,调用基类方法

同样使用作用域解析运算符::

class Fish
{
protected:
    bool isFreshWaterFish;
    Fish(bool isFreshWater):isFreshWaterFish(isFreshWater){};

public:

    void Swim(){
        if (isFreshWaterFish)
        {
            cout<<"swim in lake"<<endl;
        }
        else{
            cout<<"swim in sea"<<endl;
        }        
    }
};

class Tuna:public Fish{
public:
    Tuna():Fish(false){};
     void Swim(){//覆盖基类中的方法
        cout<<"fu gai"<<endl;
        Fsih::Swim();//调用基类方法
     }

};

7.派生类中隐藏的基类方法

覆盖是一种极端情况,即派生类中的重载方法会隐藏基类中方法的所有重载版本,导致需要调用时无法调用,示例代码如下

#include <iostream> 
using namespace std;
// 定义基类Fish
class Fish {
public:
    // 定义一个成员函数Swim
    void Swim() {
        cout << "Fish swim" << endl;
    }

    // 重载Swim函数,带有一个布尔参数isFreshWaterFish
    void Swim(bool isFreshWaterFish) {
        if (isFreshWaterFish) {
            cout << "swim in lake" << endl;
        } else {
            cout << "swim in sea" << endl;
        }
    }
};

// 定义派生类Tuna,
class Tuna : public Fish {
public:
    // 重写基类Fish的Swim成员函数
    void Swim() {
        cout << "fu gai" << endl;
    }
};


int main() {
    Tuna dinner; // 创建Tuna类的对象dinner

    cout << "dinner: " << endl; 
    dinner.Swim(); // 调用dinner对象的Swim函数,由于Tuna类重写了Swim,所以调用的是Tuna类的Swim

	dinner.Swim(false); //ERROR,因为派生类中的重载函数Swim(bool isFreshWaterFish)已经被覆盖了

    system("pause"); 
    return 0; 

若想调用基类中的方法

解决办法1: 使用作用域解析符::

dinner.Fish::Swim(false);

解决方法2: 在派生类中使用using解除隐藏

#include <iostream>
using namespace std;

class Fish
{


public:

    void Swim(){
        cout<<"Fish swim"<<endl;
    }

    void Swim(bool isFreshWaterFish){
        if (isFreshWaterFish)
        {
            cout<<"swim in lake"<<endl;
        }
        else{
            cout<<"swim in sea"<<endl;
        }        
    }
};

class Tuna:public Fish{
public:
     using Fish::Swim;//解除隐藏
     void Swim(){
        cout<<"fu gai"<<endl;
     }

};

 
 int main(){
    Tuna dinner;

    cout<<"dinner: "<<endl;
    dinner.Swim();
    dinner.Swim(false);//可以正常调用了
    system("pause");
    return 0;
 }

解决方法3: 在派生类中,把基类中的方法全部重载一次,且在重载方法中就调用基类方法

#include <iostream>
using namespace std;

class Fish
{

public:
    void Swim(){
        cout<<"Fish swim"<<endl;
    }

    void Swim(bool isFreshWaterFish){
        if (isFreshWaterFish)
        {
            cout<<"swim in lake"<<endl;
        }
        else{
            cout<<"swim in sea"<<endl;
        }        
    }
};

class Tuna:public Fish{
public:
	//重载基类中的方法Swim()
     void Swim(){
        cout<<"fu gai"<<endl;
     }
	//重载基类中的重载方法Swim(bool isFreshWaterFish)
     void Swim(bool isFreshWaterFish){
        Fish::Swim(isFreshWaterFish);//直接调用基类中的方法
    }

};

 int main(){
    Tuna dinner;

    cout<<"dinner: "<<endl;
    dinner.Swim();
    dinner.Swim(false);//可以正常运行了
    system("pause");
    return 0;
 }
  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 《21天学通C 第8版》是一本系统介绍C语言基础知识的教材。全书分为21个章节,旨在帮助读者在21天内掌握C语言的基本语法、数据类型、运算符、流程控制语句、数组和指针、函数与递归等知识点,并能完成简单的编程练习。 该书的优点在于系统性强、简明易懂、内容涵盖面广。每一章节都设置了知识点总结和习题练习,读者在看完后可以通过练习加深对知识点的理解和掌握。同时,《21天学通C 第8版》还附带了光盘,内含配套的编程软件和课程视频,方便读者边学边练,在实践中掌握C语言的应用。 不过,《21天学通C 第8版》也有一些缺点。书中部分内容略显单薄,有些知识点缺乏深度讲解。同时,随着C语言发展和应用的日益广泛,该书的内容已经有些落后,没有覆盖到一些现代C语言编程的技术和工具。此外,对于初学者来说,21天的学习时间有些紧张,对于基础薄弱的读者可能需要更长时间的学习和练习。 总体而言,如果你是初学者,并且想快速入门C语言编程,那么《21天学通C 第8版》是一本不错的教材。但如果你已经有了一定的编程基础,或者想学习更深入的C语言编程知识,那么建议结合其他教材和实践项目进行学习。 ### 回答2: 《21天学通C》第8版是一本深入浅出、适合初学者学习C语言的经典教程。本书从C语言基础开始,系统地介绍了语言的各个方面,包括语法、数据类型、运算符、表达式、循环、分支、函数、指针、结构体、数据存储和IO操作等内容,每一章节都有丰富的例子和练习题,帮助读者更好地理解和掌握知识点。 这本书的特点是结构清晰、示例详细、实现灵活、应用广泛。它不仅讲解了C语言的基本语法和编程技巧,还涉及了一些高级话题,例如控制台程序、文件操作、数据结构和算法等。此外,本书还介绍了一些实际应用中常用的C库函数和工具,例如stdio.h、stdlib.h、string.h、time.h、make和gcc等。 学习这本书不仅能够帮助初学者快速掌握C语言,还能够提高他们的编程能力和实践经验。本书的内容深入浅出,涵盖全面,适合广大学生、初学者、自学者和编程爱好者使用,它也是一本值得长期保留和经常翻阅的经典教材。 ### 回答3: 《21天学通C》是一本经典的编程入门教材,旨在帮助初学者快速掌握C语言编程基础知识,从而能够编写简单的C程序。第8版在原有基础上进行了全面更新和完善,内容更加丰富、实用。 本书共分为21天的学习计划,每天均有相应的课程安排和练习题。第一天介绍了C语言的概述及编译器的使用,第二天开始介绍变量、数据类型、表达式等基础知识,随后每天的内容都逐渐加深,包括运算符、流程控制、函数、数组、指针等重要的C语言特性。每一章节都采用了清晰而易懂的语言和实例说明,让初学者能够更快的理解和掌握C语言。 值得一提的是,本书的第21天还特别介绍了一些高级的C语言编程技巧和应用,如结构体、文件操作、内存动态分配、多线程等,这些知识对于想进一步深入学习C语言的人来说非常有帮助。 总体而言,《21天学通C》第8版是一本经典而实用的编程入门教材,很好地贯穿了C语言的基础和高级知识点,能够让初学者快速掌握并灵活运用C语言编程技能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青石横刀策马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值