【C++学习笔记2】构造函数、析构函数、函数多态、抽象类、函数模板

本文详细介绍了C++中的构造函数、析构函数、函数多态和抽象类的概念及其应用。构造函数用于对象初始化,析构函数在对象销毁时执行,常用于资源释放。函数多态分为静态多态和动态多态,动态多态通过虚函数实现。抽象类含有纯虚函数,不能实例化,常用于接口定义。函数模板则提供了一种代码重用的方式,可以根据不同类型参数自动生成函数代码。
摘要由CSDN通过智能技术生成

这次笔记介绍构造函数、析构函数、函数多态、抽象类、函数模板

一、构造函数 

1、在定义对象,构造函数程序将自动执行,他的类型跟类名一致

函数声明最好放在自己的类里面,这样才符合类的封装,也可以像下面一样(较麻烦)

#include <iostream>
using namespace std;
class Drgon
{
public:
    Drgon(void);
    Drgon(string str);
    void fun(void);   //把作用去掉
};
Drgon::Drgon(void)  //无参数的构造函数
{
    cout << "执行构造函数1" << endl;
}
Drgon::Drgon(string str)  //带参数的构造函数
{
    cout << "执行构造函数2:" << str <<endl;
}
void Drgon::fun(void)      //普通类函数
{
    cout << "普通执行函数" << endl;
}
int main(void)
{
    Drgon *drg1 = new Drgon();
    Drgon *drg2 = new Drgon("000");
    Drgon *drg3 = new Drgon;
    drg3->fun();
    return 0;
}


二、析构函数

        析构函数是“反向”的构造函数。它们在对象被撤消(回收)时调用。析构函数的名称除了最前面的“~”符号外,与类的名称相同,类String的析构函数是~string()。 析构函数通常用于当一个对象不再需要时,完成“消除”功能。

程序运行完就执行----可以用来释放内存

只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。

#include <iostream>
using namespace std;
class Drgon
{
public:
    Drgon(void);    //构造函数
   ~Drgon(void);    //析构函数
};
Drgon::Drgon(void)  //无参数的构造函数
{
    cout << "执行构造函数1" << endl;
    //初始化函数
}
Drgon::~Drgon(void) //无参数的析构函数
{
    cout << "执行析构函数1" << endl;
    //执行的功能
}
int main(void)
{
    Drgon *drog = new Drgon;  //创建调用构造函数
  //drog->~Drgon();
    delete drog;//销毁
    return 0;
}


三、函数多态

什么是多态?

顾名思义就是同一个事物在不同场景下的多种形态

分为静态多态和动态多态

静态多态

静态多态是编译器在编译期间完成的,编译器会根据实参类型来选择调用合适的函数,如果有合适的函数可以调用就调,没有的话就会发出警告或者报错

动态多态

显然这和静态多态是一组反义词,它是在程序运行时根据基类的引用(指针)指向的对象来确定自己具体该调用哪一个类的虚函数。

动态多态的条件:

●基类中必须包含虚函数,并且派生类中一定要对基类中的虚函数进行重写。

●通过基类对象的指针或者引用调用虚函数。

概念:同函数重载差不多,多态在不同继承关系的类对象,调用同一函数,产生不一样的效果,例如:一个软件下新用户是有优惠的,而老用户没有优惠、此时就需要某一种技术(方法)做到优惠。

例子:

#include <iostream>
using namespace std;
class Drgon{
public:
    virtual void Shoping(){
        cout << "老用户:买东西-全价" << endl;
    }
};
class New_Drgon : public Drgon{
  public:
    virtual void Shoping() {
        cout << "新用户:买东西-半价" << endl;
    }
};
void fun(Drgon&p){
    p.Shoping();
}
int main(void){
    Drgon ps;   //老用户
    New_Drgon pt; //新用户
    fun(ps);  //根据传入的对象来分辨
    fun(pt);
    return 0;
}


总结一道面试题:

问:哪些函数不能定义为虚函数?

经检验下面的几个函数都不能定义为虚函数:

1)友元函数,它不是类的成员函数

2)全局函数

3)静态成员函数,它没有this指针

3)构造函数,拷贝构造函数,以及赋值运算符重载(可以但是一般不建议作为虚函数)

四、抽象类

在成员函数(必须为虚函数)的形参列表后面写上=0,则成员函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。

①纯虚函数在派生类中重新定义以后,派生类才能实例化出对象。

②纯虚函数是一定要被继承的,否则它存在没有任何意义。

实例:

#include <iostream>
using namespace std;
class Base {  //基类
public:
   virtual void Drive() = 0; //纯虚函数
};
class Drived1 :public Base { //派生类
   virtual void Drive(){
        cout << "第一种" << endl;
    }
};
class Drived2 :public Base  {//派生类
   virtual void Drive(){
        cout << "第二种" << endl;
    }
};
int main(){
   Base *pDrived1 = new Drived1;
   pDrived1 ->Drive();
   Base *pDrived2 = new Drived2;
   pDrived2 ->Drive();
    return 0;
}


五、函数模板

概念:函数模板不是一个实在的函数,编译器不能为其生成可执行代码。定义函数模板后只是一个对函数功能框架的描述,当它具体执行时,将根据传递的实际参数决定其功能。

格式:

template <class 类型参数1, class类型参数2, ...> 返回值类型 模板名(形参表) { 函数体 } 其中的 class 关键字也可以用 typename 关键字替换。

例如: template <typename 类型参数1, typename 类型参数2, ...>

用法:

面向对象的继承和多态机制有效提高了程序的可重用性和可扩充性。在程序的可重用性方面,程序员还希望得到更多支持。举一个最简单的例子,为了交换两个整型变量的值,需要写下面的 Swap 函数:

void Swap(int & x, int & y){ int tmp = x; x = y; y = tmp; }

为了交换两个 double 型变量的值,还需要编写下面的 Swap 函数:

void Swap (double & xr double & y){ double tmp = x; x = y; y = tmp; }

如果还要交换两个 char 型变量的值,交换两个 CStudent 类对象的值……都需要再编写 Swap 函数。而这些 Swap 函数除了处理的数据类型不同外,形式上都是一样的。能否只写一遍 Swap 函数,就能用来交换各种类型的变量的值呢?继承和多态显然无法解决这个问题。因此,“模板”的概念就应运而生了。

程序设计语言中的模板就是用来批量生成功能和形式都几乎相同的代码的。有了模板,编译器就能在需要的时候,根据模板自动生成程序的代码。从同一个模板自动生成的代码,形式几乎是一样的。

实例:

#include <iostream>
using namespace std;
template <typename T>
T Swap(const T a,const T b){   //函数模板
    T sp=a+b;
    return sp;
}
int main(){
    int n = 1, m = 2;
    double f=3.12,g=4.12;
    cout << Swap(n, m) << endl;//编译器自动生成 void Swap (int &, int &)函数
    cout << Swap(f, g) << endl; //编译器自动生成 void Swap (double &, double &)函数
    return 0;
}

1. 请创建一个抽象类DataStructure,该类包括下面的成员变量和成员函数: 1) 一个成员变量len,表示里面的元素个数最大值 2) 构造函数DataStructure(int l),将len初始化为0 3) 虚析构函数~DataStructure() 4) 纯虚函数Output(),输出DataStructure中的数据 5) 纯虚函数Size(),返回DataStructure中的元素个数 2. 请创建DataStructure的一个派生类MyString,该类包括下面的成员变量和成员函数: 1) 一个成员变量char* data,表示里面的数据 2) 构造函数MyString(int max_size),将MyString初始化为空串,最大元素个数为max_size 3) 析构函数~MyString(),释放相应的数据 4) Input()函数,往MyString输入数据 5) 重载operator+=()函数,实现两个字符串的连接 6) 重定义Output()和Size()函数 3. 请创建DataStructure的一个派生类MyStack,该类包括下面的成员变量和成员函数: 1) 一个成员变量int* data,用于里面的数据 2) 一个成员变量int top,表示最上面的元素下标 3) 构造函数MyStack(int max_size),将MyStack初始化为空栈,最大元素个数为max_size 4) 析构函数~MyStack(),释放相应的数据 5) Push_back(int e)函数,往栈里面压入一个数据e 6) 重定义Output()和Size()函数 4. 请编写main函数,测试上面程序的正确性 1) 创建两个MyString的对象str1和str2,分别调用Input函数输入str1和str2,然后分别调用operator+=函数将str2连接到str1的末尾 2) 创建一个MyStack的对象stack,调用Push_back函数输入往stack中输入m(m < max_size)个数据 3) 创建一个长度为3的DataStructure*类型的数组,将其3个元素分别指向str1, str2, stack,然后编写for循环调用Size()和Output()函数输出每个元素的大小和内容。 5. 输入输出样例: 1) 输入样例 A promising techni que for checking reachability 4 12 23 34 45 2) 输出样例 47 A promising technique for checking reachability 29 que for checking reachability 4 12 23 34 45
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值