Modern C++ 之面向对象

委托构造函数(Delegate constructor)

C++11引入了Delegate Constructor 的概念,用于在一个类中让一个构造函数使用另外一个构造函数,从而用来简化初始化的代码

Talk is cheap, show me the code.下面定义基类Base,里面含有两个变量并且含有两个构造函数,其中带参数的构造函数会调用不带参的构造函数,完整示例代码如下所示:

class Base
{
public:
    int value1;
    int value2;

public:
    Base()
    {
        value1 = 1;
    }

    // 使用Delegete Base方法,用来简化code
    Base(int value) :Base()
    {
        value2 = value;
    }
};

构造函数的继承

一个类只能初始化它的的直接基类,也就是说一个类只能继承直接基类的构造函数。类不能继承默认、拷贝和移动构造函数。在传统的C++中,如果一个类要继承基类的构造函数,那么需要将参数一个个传递,效率较低。在C++11中,可以使用using声明语句直接继承基类的构造函数

class SubBase :public Base
{
public:
    using Base::Base;    // 继承构造函数
};

精确地重写虚函数

在传统C++中,很有可能会出现重写虚函数的操作,一个简单的示例代码如下所示:

struct Base {
    virtual void foo(int);
};
// 
struct SubBase :Base {
    void foo();    // overload foo function in Base, or just write a new function
};

从上面的代码中分析可以得知,SubBase中的foo有可能是用来重载Basefoo函数,又或者是直接新写一个名字相同的函数。但是这样会存在一个问题:如果basefoo函数被删除了,那么SubBase里的foo函数就不再是重写虚函数了,而是一个普通的函数了,这种问题就很容易迷惑自己。

为了解决上面的迷惑行为,C++11引入了两个关键字overridefinal,用于解决上面所说的问题。

override

如果需要重写一个函数,那么可以使用override关键字进行声明,之后编译器会判断父类中是否会有对应的虚函数,没有的话则无法编译通过

示例代码:

struct OverBase
{
    virtual void foo(int);
};

struct SubOverBase :OverBase
{
    virtual void foo(int) override; //合法声明
    //virtual void foo(double) override;   父类中没有对应的函数,所以声明不合法
};

final

final关键字用来限制类不在被继承或者禁止重载虚函数

struct FinalBase
{
    virtual void foo(int) final;
 };
 
struct SubFinalBase1 final :FinalBase    // legal statement
{
};

/*
* 非法定义示例
struct SubFinalBase2 :SubFinalBase1    // 非法定义,类使用final关键字限制继承
{
};

struct SubFinalBase3 :FinalBase
{
    void foo(int);    // 非法顶底,foo函数使用final限制重载
};
*/

精确地使用和删除默认构造函数

在传统C++中,如果用户在程序中没有显示写构造函数,那么编译器会自己生成默认的构造函数、拷贝构造函数和析构函数等,并且也会为所有类定义 new delete的操作。

但有的时候也会有一些特定的需求,例如精确控制默认构造函数的产生与否。打个比方,当一个类不能被复制的时候,那么类中的拷贝构造函数和一些操作都必须被声明位private。如果我们尝试去使用这些未定义的方法,那么将会引起错误;

并且,当用户定义了构造函数的时候,那么类的默认构造函数是不会存在的,但是如果我们需要类必须存在一个默认构造,这个时候就非常尴尬,因为两者不能并存啊。

为了解决上面所说的情形,C++11提供了下面的解决办法,具体使用参见示例代码:

class Magic
{
public:
    Magic() = default;    // 使用默认构造函数
    Magic& operator=(const Magic&) = delete;    // 拒绝使用
    Magic(int magic_number);
};

更强的枚举类型

传统C++中枚举类型不是类型安全的,并且是当作整形来处理的,因此可以将两个不同的枚举类型用来比较大小。并且在不同的枚举类型中,里面的枚举变量名字也不能一样,因为作用域是一样的。C++11引入了enum class或者enum struct来提高枚举类型的使用率。

enum class new_enum : unsigned int
{
    value1,
    value2,
    value3 = 100,
    value4 = 100
};
posted @ 2020-03-29 15:09  醉曦  阅读(232)  评论(0编辑  收藏  举报