类中的新特性
Published on
委托构造
同一个类中的一个构造函数可以调用另一个构造函数,从而达到简化代码的目的:
class Base
{
public:
Base()
{
value1 = 1;
}
Base(int value) : Base() // 委托Base()构造函数
{
value2 = 2;
}
private:
int value1;
int value2;
};
继承构造
假设父类有多个版本的构造函数,即使子类不进行修改,也必须编写同样多的构造函数,将参数透传至父类,例如:
class A
{
public:
A(int i) {}
A(double d, int i) {}
A(float f, int i, const char *c) {}
//......
};
class B : public A
{
public:
B(int i) : A(i) {}
B(double d, int i) : A(d, i) {}
B(float f, int i, const char *c) : A(f, i, c) {}
//......
};
在C++11以后,使用继承构造可以避免编写此类重复代码:
class A
{
public:
A(int i) {}
A(double d, int i) {}
A(float f, int i, const char *c) {}
//......
};
class B : public A
{
using A::A; // 使用继承构造
};
final与override
final关键字可修饰一个类,以禁止该类被继承;也可修饰一个虚函数,以禁止该函数被子类重写:
class Base final
{
};
// 错误,Base不能被继承
class Derived : public Base
{
};
class Base
{
virtual void func() final
{
std::cout << "base" << std::endl;
}
};
class Derived : public Base
{
// 错误,func不能被重写
void func() override
{
std::cout << "derived" << std::endl;
}
};
与final相反,当使用override关键字修饰一个函数时,此函数必须重写父类的虚函数,如果父类没有该虚函数则会报错:
class Base
{
virtual void func()
{
std::cout << "base" << std::endl;
}
};
class Derived : public Base
{
// 确保func()重写虚函数
void func() override
{
std::cout << "derived" << std::endl;
}
// 错误,父类没有fu()函数,不可以重写
void fu() override
{
}
};
delete与default
C++编译器有时会自动生成一些默认函数。例如,如果用户没有为一个类声明任何构造函数,则编译器会生成一个默认构造函数:
class A
{
};
A a; // 由于存在默认构造函数,此行代码可运行
如果想要禁止编译器生成默认函数,可使用delete关键字:
class A
{
A() = delete;
};
A a; // 由于删除了默认构造函数,此行代码不可运行
某些情况下,用户没有编写某个函数,编译器也没有生成默认版本。例如,当用户为一个类声明任意一个构造函数后,编译器不会生成默认构造函数:
class A
{
public:
A(int i) {}
};
A a; // 未生成默认构造函数,此行代码不可运行
此时,如果需要默认版本的函数,可使用default关键字要求编译器生成:
class A
{
public:
A() = default;
A(int i) {}
};
A a; // 生成了默认构造函数,此行代码可运行
explicit
explicit用于修饰构造函数,表示只能显式构造,不可以被隐式转换。
class A
{
public:
// 未使用explicit关键字
A(int value)
{
std::cout << "value" << std::endl;
}
};
A a = 1; // 可以隐式转换
class A
{
public:
// 使用了explicit关键字
explicit A(int value)
{
std::cout << "value" << std::endl;
}
};
A a = 1; // 错误,不可以隐式转换
A aa(2); // 正确,显式调用构造函数