C++与类相关的关键词和修饰符说明

在C++11中,新增了  override 和 final 说明符;编译器更是能识别出左值和右值,对于成员函数,新增 & 和 &&类型限定符。&用来说明该成员函数只能被左值对象调用,&&用来说明该成员函数只能被右值对象调用。

总结关于 this 指针类型的限定符 const, & 和 &&。这三个限定符都是说明this 指针类型的,函数的参数的类型是函数签名的一部分,所以在类外给出函数的实现时,这三个类型限定符不能少(当然这也符合一致性原则,声明与定义一致)。否则会爆 原型跟定义不一致的错误。

class Base
{
public:
    virtual Base* copy() const & = 0;
};

class Derived: public Base
{
public:
    virtual Base* copy() const &;
};

Base* Derived::copy() const &
    {
        return new Derived;
    }

static, friend, virtual, final, override,explicit 只是用来说明,本身跟类型信息无关。finnal 用来说明类不能被继承或者虚函数的实现必须被派生类继承;override 用来说明此虚函数只是继承了接口,在派生类中重新实现。以前的黑科技用虚继承 + 友元来实现禁止继承。

所以在类外给出相应的static变量,友元函数,虚函数的定义时,不用再写上这些说明符:因为这些说明符本来就不是表达 this 类型信息的。

另外,delete 用来禁止编译器合成特定的成员函数,defult 强制编译器合成;noexcept 表示函数不会抛出异常,constexpr 表示函数的结果在编译器就能得到。

delete关键字的妙用

任何函数都可标记为delete,普通函数,成员函数, 甚至函数模板的特化版本;这样可以用来禁止某些重载版本和函数模板的特化版本。

如果想让函数只能接受某种类型T 的参数,而拒绝所有可以隐式转化为该类型的参数,可以声明该函数相同的一个模板版本,然后把模板版本标记为 delete,这样任意非类型T 的参数在调用时都会决议去匹配模板版本,而delete标记 会导致调用失败。

代码如下:

void intOnly(int x)
{
    std::cout << "int parameter only";
}

template <typename T>
void intOnly(T x) = delete;

intOnly(3.14);//error

explicit 关键字的说明

explicit关键字用来修饰内的构造函数,准确的来说,是单参数构造函数,表示不能隐式的由单参数转化为类对象。

class Myclass
{
public:
    Myclass(int i)   //version 1
    {

    }
};
Myclass obj = 3;   //语义上,这句会先隐式的调用构造函数,然后再调用拷贝构造函数,不过由于返回值优化(RVO技术),实际上会优化掉拷贝构造函数的调用
                  //可将拷贝构造函数设为private 或者标记为 delete来,会发现编译不过

将构造函数加上explicit关键字,会发现编译不过。

class Myclass
{
public:
    explicit Myclass(int i)
    {

    }
};
<pre name="code" class="cpp">Myclass obj = 3;   //编译不过   只能 Myclass obj(3);

 

由于拷贝构造函数也是当参数的,所以拷贝构造函数也可以标记为explict。

class Myclass
{
public:
    explicit Myclass(int i)
    {

    }
    explict Myclass(const Myclass&)
    {

    }
};

Myclass obj{ 3 };
Myclass objTem = obj;   //编译不过   只能Myclass objTem(obj);
也就是说,用 "=" 赋值运算符发生的是构造函数的隐式调用;用 “()” 函数调用运算符发生的是显示的构造函数的调用(或者C++11中提供的统一初始化也是显示调用),而参数传递时,如果是传值,此时如果内的拷贝构造函数为explicit, 将会因为没有匹配的拷贝构造函数而出错。要清楚拷贝构造和赋值构造函数的不同。

class Myclass
{
public:
    explicit Myclass(int i)
    {

    }
    explicit Myclass(const Myclass&)
    {

    }
};

void test(Myclass arg)
{

}

Myclass obj{ 3 };
test(obj);   //传值时出错,没有合适的拷贝构造函数

将上边函数更改如下:

void test(Myclass& arg)
{
    Myclass localObj(arg);   //通过
}
此时可以通过,localObj的构造是显示的调用拷贝构造函数


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值