C++ default、delete、overrride、final声明函数

default:

当我们手动创建一个有参构造函数后,编译器不是提供默认的无参构造函数,但是有时候程序中可能会用到,这时候可以使用default声明,让编译器提供默认的构造函数。

#include <iostream>
using namespace std;


class A {
public:
    // A user-defined
    A(int x){
        cout << "This is a parameterized constructor";
    }


    // Using the default specifier to instruct
    // the compiler to create the default implementation of the constructor.
    A() = default;
};


int main(){
    A a;          //call A()
    A x(1);       //call A(int x)
    cout<<endl;
    return 0;
}

default使用限制:
默认函数需要用于特殊的成员函数(默认构造函数,复制构造函数,析构函数等),或者没有默认参数

作用:
使用“{}”简单的空的实体时,使用’= default’有什么优点?
尽管两者可能表现相同,但使用default而不是使用{}仍然有一定的好处。以下几点做了一定的解释:

  1. 给用户定义的构造函数,即使它什么也不做,使得类型不是聚合,也不是微不足道的。如果您希望您的类是聚合类型或普通类型(或通过传递性,POD类型),那么需要使用’= default’。
  2. 使用’= default’也可以与复制构造函数和析构函数一起使用。例如,空拷贝构造函数与默认拷贝构造函数(将执行其成员的复制副本)不同。对每个特殊成员函数统一使用’= default’语法使代码更容易阅读。

delete

用作声明函数: 用于显式禁用某些函数。
与default不同的是,delete没有限制函数必须是类的特殊成员函数。

#include <bits/stdc++.h>
using namespace std;


class LiF {
public:
    LiF() = default;
    LiF(int _lif) {
        lif = _lif;
    }
    LiF(const LiF& l) = delete; // 显式禁用拷贝构造函数
    LiF& operator= (const LiF& l) = delete; // 显式禁用拷贝赋值运算符

    void print(){cout << lif << endl;}

    ~LiF() = default;
private:
    int lif;
};

int main() {
    LiF* lif1 = new LiF{2};
    LiF lif2 = *lif1; // 这里将引发报错,因为拷贝赋值运算符已被显式禁用
    lif2.print();
    delete lif1;
    lif1 = nullptr;
    return 0;
}

double add(double x, double y) {
    return x + y;
}
int add(int, int) = delete; // 显式禁用add函数的int版本


int main() {
    int a, b;
    add(a, b); // 这里将引发报错,因为对应的函数已被显式禁用
    return 0;
}

这里有一点需要注意的是,delete关键字仅仅禁用了函数的调用,但在编译过程中,名字查找和重载解析时,该函数名仍是一个有效的标识符。
分析第二个例子:我们声明并定义了double类型的add函数,声明并显式禁用了add函数的int重载。在编译到add(a, b)时,编译器进行名字查找,找到全局作用域的add函数定义,并通过精确匹配最终定位到int add(int, int)这个重载上,随后编译器发现这是一个deleted(已被禁用)函数,引发报错。

override:

override 显式声明了成员函数是一个虚函数且覆盖了基类中的该函数。
如果有 override 声明的函数不是虚函数,或基类中不存在这个虚函数,编译器会报告错误。
作用:
这个说明符的主要作用有两个:

  1. 给开发人员更明确的提示,这个函数覆写了基类的成员函数;
  2. 让编译器进行额外的检查,防止程序员由于拼写错误或代码改动没有让基类和派生类中的成员函数名称完全一致。

final :

1、则声明了成员函数是一个虚函数,且该虚函数不可在派生类中被覆盖。如果有一点没有得到满足的话,编译器就会报错。
2、final 还有一个作用是标志某个类或结构不可被派生。同样,这时应将其放在被定义的类或结构名后面。

class A {
public:
  virtual void foo();
  virtual void bar();
  void foobar();
};


class B : public A {
public:
  void foo() override; // OK
  void bar() override final; // OK
  //void foobar() override;
  // 非虚函数不能 override
};


class C final : public B {
public:
  void foo() override; // OK
  //void bar() override;
  // final 函数不可 override
};


class D : public C {
  // 错误:final 类不可派生};
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值